├── CMakeLists.txt ├── LICENSE.md ├── README.md ├── RS41HUP.elf ├── arm-gcc-link.ld ├── cmake-clean ├── cmsis ├── .readme.md ├── core_cm3.h ├── core_cmFunc.h └── core_cmInstr.h ├── cmsis_boot ├── .readme.md ├── startup │ ├── .readme.md │ └── startup_stm32f10x_md_vl.c ├── stm32f10x.h ├── stm32f10x_conf.h ├── system_stm32f10x.c └── system_stm32f10x.h ├── config.h ├── delay.c ├── delay.h ├── docs └── programming_header.md ├── flash.sh ├── init.c ├── init.h ├── main.c ├── morse.c ├── morse.h ├── pwm.c ├── pwm.h ├── radio.c ├── radio.h ├── stm_lib ├── .readme.md ├── inc │ ├── .readme.md │ ├── misc.h │ ├── stm32f10x_adc.h │ ├── stm32f10x_dma.h │ ├── stm32f10x_flash.h │ ├── stm32f10x_gpio.h │ ├── stm32f10x_pwr.h │ ├── stm32f10x_rcc.h │ ├── stm32f10x_spi.h │ ├── stm32f10x_tim.h │ └── stm32f10x_usart.h └── src │ ├── .readme.md │ ├── misc.c │ ├── stm32f10x_adc.c │ ├── stm32f10x_dma.c │ ├── stm32f10x_flash.c │ ├── stm32f10x_gpio.c │ ├── stm32f10x_pwr.c │ ├── stm32f10x_rcc.c │ ├── stm32f10x_spi.c │ ├── stm32f10x_tim.c │ └── stm32f10x_usart.c ├── syscalls ├── .readme.md └── syscalls.c ├── ublox.c ├── ublox.h ├── util.c └── util.h /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.6) 2 | include(CMakeForceCompiler) 3 | SET(CMAKE_SYSTEM_NAME "Generic") 4 | SET(CMAKE_SYSTEM_VERSION 1) 5 | 6 | 7 | # 8 | # Set toolchain path below. 9 | # 10 | 11 | if (UNIX) 12 | set(TOOLCHAIN_DIR "$ENV{HOME}/opt/gcc-arm-none-eabi/bin") 13 | CMAKE_FORCE_C_COMPILER(${TOOLCHAIN_DIR}/arm-none-eabi-gcc GNU) 14 | CMAKE_FORCE_CXX_COMPILER(${TOOLCHAIN_DIR}/arm-none-eabi-g++ GNU) 15 | else () 16 | set(TOOLCHAIN_DIR "D:/Programy/GNU Tools ARM Embedded/5.4 2016q3/bin") 17 | CMAKE_FORCE_C_COMPILER(${TOOLCHAIN_DIR}/arm-none-eabi-gcc.exe GNU) 18 | CMAKE_FORCE_CXX_COMPILER(${TOOLCHAIN_DIR}/arm-none-eabi-g++.exe GNU) 19 | endif () 20 | 21 | 22 | # 23 | # Select a method of programming below. 24 | # 25 | 26 | set(USE_OPENOCD "true") 27 | #set(USE_ST_FLASH "true") 28 | #set(USE_BLACK_MAGIC "true") 29 | 30 | 31 | project(RS41FOX C CXX) 32 | 33 | add_definitions(-DSTM32F100C8) 34 | add_definitions(-DSTM32F10X_MD_VL) 35 | add_definitions(-DUSE_STDPERIPH_DRIVER) 36 | add_definitions(-DSUPPORT_CPLUSPLUS) 37 | add_definitions(-D__ASSEMBLY__) 38 | 39 | SET(LINKER_SCRIPT ${PROJECT_SOURCE_DIR}/arm-gcc-link.ld) 40 | SET(COMMON_FLAGS " -mcpu=cortex-m3 -mthumb -Wall -ffunction-sections -g -O3 -g -nostartfiles ") 41 | SET(CMAKE_CXX_FLAGS "${COMMON_FLAGS} -std=c++11") 42 | SET(CMAKE_C_FLAGS "${COMMON_FLAGS} -std=gnu99") 43 | SET(CMAKE_EXE_LINKER_FLAGS "-Wl,-Map=${CMAKE_BINARY_DIR}/${PROJECT_NAME}.map -lstdc++ -O3 -Wl,--gc-sections --specs=nano.specs -T ${LINKER_SCRIPT}") 44 | 45 | file(GLOB_RECURSE USER_SOURCES "*.c") 46 | file(GLOB_RECURSE USER_SOURCES_CXX "*.cpp") 47 | file(GLOB_RECURSE USER_HEADERS "*.h") 48 | 49 | include_directories(cmsis 50 | cmsis_boot 51 | stm_lib/inc 52 | .) 53 | 54 | add_executable(${PROJECT_NAME}.elf ${USER_SOURCES} ${USER_SOURCES_CXX} ${USER_HEADERS} ${HAL_SOURCES} ${LINKER_SCRIPT}) 55 | 56 | set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-Map=${CMAKE_BINARY_DIR}/${PROJECT_NAME}.map") 57 | set(HEX_FILE ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.hex) 58 | set(BIN_FILE ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.bin) 59 | add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD 60 | COMMAND ${CMAKE_OBJCOPY} -Oihex $ ${HEX_FILE} 61 | COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${BIN_FILE} 62 | COMMENT "Building ${HEX_FILE} \nBuilding ${BIN_FILE}" 63 | COMMAND ${TOOLCHAIN_DIR}/arm-none-eabi-size ${PROJECT_NAME}.elf) 64 | 65 | set(CMAKE_CXX_STANDARD 11) 66 | 67 | 68 | # 69 | # make erase 70 | # 71 | # Does a security unlock, followed by a flash erase. 72 | # 73 | # Just doing an unlock on its own would only erase the flash, if the device had 74 | # previously been locked. To avoid surprising the user, we always erase the 75 | # flash. 76 | # 77 | # Note that security unlock is currently only supported if using openocd. 78 | # 79 | # 80 | # make halt 81 | # 82 | # Resets and then halts the device. 83 | # 84 | # 85 | # make run 86 | # 87 | # Resets and then runs the device. 88 | # 89 | # 90 | # make program-halt 91 | # 92 | # Programs the device, and leaves it halted. 93 | # 94 | # Does not require the device to be erased first, although it must not be 95 | # security locked. 96 | # 97 | # 98 | # make program 99 | # 100 | # Programs the device, and allows it to run after reset. 101 | # 102 | # Does not require the device to be erased first, although it must not be 103 | # security locked. 104 | # 105 | 106 | 107 | if (USE_OPENOCD) 108 | 109 | add_custom_target(erase 110 | COMMENT "Unlocking and erasing device" 111 | COMMAND openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c \"init\; reset halt\; stm32f1x unlock 0\; reset halt\; flash protect 0 0 last off\; reset halt\; flash erase_sector 0 0 last\; reset halt\; exit\" 112 | ) 113 | add_custom_target(halt 114 | COMMENT "Resetting and halting device" 115 | COMMAND openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c \"init\; reset halt\; exit\" 116 | ) 117 | add_custom_target(run 118 | COMMENT "Resetting device and then running" 119 | COMMAND openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c \"init\; reset\; exit\" 120 | ) 121 | add_custom_target(program-halt 122 | DEPENDS ${PROJECT_NAME}.elf 123 | COMMENT "Programming device with ${HEX_FILE}, and then halting" 124 | COMMAND openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c \"program ${HEX_FILE} verify exit\" 125 | ) 126 | add_custom_target(program 127 | DEPENDS ${PROJECT_NAME}.elf 128 | COMMENT "Programming device with ${HEX_FILE}, and then running" 129 | COMMAND openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c \"program ${HEX_FILE} verify reset exit\" 130 | ) 131 | 132 | elseif (USE_ST_FLASH) 133 | 134 | add_custom_target(erase 135 | COMMENT "Erasing device" 136 | COMMAND st-flash erase 137 | COMMAND echo If unlocking is required, please select openocd in CMakeLists.txt 138 | ) 139 | add_custom_target(halt 140 | COMMENT "Halting the device is not supported by st-link" 141 | COMMAND echo If halting is required, please select openocd in CMakeLists.txt 142 | ) 143 | add_custom_target(run 144 | COMMENT "Resetting device and then running" 145 | COMMAND st-flash reset 146 | ) 147 | add_custom_target(program-halt 148 | COMMENT "Halting the device is not supported by st-link" 149 | COMMAND echo If halting is required, please select openocd in CMakeLists.txt 150 | ) 151 | add_custom_target(program 152 | DEPENDS ${PROJECT_NAME}.elf 153 | COMMENT "Programming device with ${HEX_FILE}, and then running" 154 | COMMAND st-flash --reset --format ihex write ${HEX_FILE} 155 | ) 156 | 157 | elseif (USE_BLACK_MAGIC) 158 | 159 | add_custom_target(erase 160 | COMMENT "Erasing the device is not supported with Black Magic Probe" 161 | COMMAND echo If erasing is required, please select another programming method in CMakeLists.txt 162 | ) 163 | add_custom_target(halt 164 | COMMENT "Halting the device is not supported with Black Magic Probe" 165 | COMMAND echo If halting is required, please select openocd in CMakeLists.txt 166 | ) 167 | add_custom_target(run 168 | COMMENT "make run is not supported with Black Magic Probe" 169 | COMMAND echo If erasing is required, please select another programming method in CMakeLists.txt 170 | ) 171 | add_custom_target(program-halt 172 | COMMENT "Halting the device is not supported with Black Magic Probe" 173 | COMMAND echo If halting is required, please select openocd in CMakeLists.txt 174 | ) 175 | add_custom_target(program 176 | DEPENDS ${PROJECT_NAME}.elf 177 | COMMENT "Programming device with ${PROJECT_NAME}.elf, and then running" 178 | COMMAND chmod u+x flash.sh 179 | COMMAND ./flash.sh 180 | ) 181 | 182 | else () 183 | 184 | add_custom_target(erase 185 | COMMENT "No method of programming is available" 186 | COMMAND echo Edit CMakeLists.txt and select a method of programming. 187 | ) 188 | add_custom_target(halt 189 | COMMENT "No method of programming is available" 190 | COMMAND echo Edit CMakeLists.txt and select a method of programming. 191 | ) 192 | add_custom_target(run 193 | COMMENT "No method of programming is available" 194 | COMMAND echo Edit CMakeLists.txt and select a method of programming. 195 | ) 196 | add_custom_target(program-halt 197 | COMMENT "No method of programming is available" 198 | COMMAND echo Edit CMakeLists.txt and select a method of programming. 199 | ) 200 | add_custom_target(program 201 | COMMENT "No method of programming is available" 202 | COMMAND echo Edit CMakeLists.txt and select a method of programming. 203 | ) 204 | 205 | endif () 206 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | {description} 294 | Copyright (C) {year} {fullname} 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | {signature of Ty Coon}, 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RS41-FOX - RS41 Amateur Radio Direction Finding (Foxhunting) Beacon 2 | This codebase turns a Vaisala RS41 into a 70cm 'radio fox', suitable for use in amateur radio direction finding contests. 3 | 4 | This is a fork of https://github.com/darksidelemm/RS41HUP, which is itself a fork of https://github.com/df8oe/RS41HUP. 5 | 6 | Features: 7 | * Morse Ident containing callsign & current battery voltage. 8 | * Long CW beacon (user-defined length and number of repeats) 9 | * Low-Voltage Cutout, to avoid destroying rechargable batteries. 10 | * Beacon GPS position when battery is below a user-defined threshold. 11 | 12 | ## Configuration 13 | Configuration settings are located in [config.h](./config.h). Modify as appropriate before compiling/programming. 14 | 15 | ## Compilation 16 | (Currently only supporting compilation with GCC under Linux/OSX) 17 | 18 | * Grab the latest GNU ARM Embedded toolchain from here: https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads 19 | * Extract the tarball to somewhere useful. In my case I'm using ~/opt/ 20 | * Within the RS41HUP directory: 21 | * Edit CMakeLists.txt and set the correct path to the un-tar'd directory. 22 | * Optionally enable a method of programming, in CMakeLists.txt. 23 | * `cmake .` 24 | * `make` 25 | 26 | ## Programming 27 | Either: 28 | * Use the ST Micro ST-LINK utility (Windows only), or 29 | * [openocd](http://openocd.org) under Linux/OSX/Windows, or 30 | * [stlink](https://github.com/texane/stlink) under Linux/OSX/Windows, or 31 | * Use `flash.sh` with a [Black Magic Probe](https://1bitsquared.com/products/black-magic-probe). You will need to modify this script with the path to the debugger's serial interface. 32 | 33 | Only the proprietary ST-LINK utility, or openocd, are known to support unlocking the device to remove the original manufacturer's firmware. 34 | 35 | Refer to [this file](./docs/programming_header.md) for programming header pinouts. Note that you will need to power up the RS41 using the power button, before you will be able to interact with the MCU chip. 36 | 37 | Please do not allow the RS41 to run the original manufacturer's firmware, as this will result in unlicensed radio transmissions. With the reset line connected to a debugger, it is possible to keep the MCU halted. However if the LED lights up after pressing the power button, then some firmware is definitely running - please erase the original firmware ASAP, or remove the batteries. 38 | 39 | The build system supports a number of useful operations via openocd or stlink: 40 | * `make erase` erases the flash, and if using openocd, unlocks a locked device 41 | * `make halt` resets and halts the device 42 | * `make run` resets the device and lets it run 43 | * `make program-halt` programs the device and halts it 44 | * `make program` programs the device and lets it run 45 | 46 | Additionally `make program` is supported with Black Magic Probe. Currently `halt` and `program-halt` are not supported with stlink. The `program` targets will first compile the firmware, if it is not up to date. 47 | 48 | A typical sequence for programming a freshly acquired RS41, would be: 49 | * openocd: `make erase program-halt` 50 | * stlink: Unlock the device using the proprietary (Windows) version of ST-LINK, and clear the flash page protection bits. Then program using either the proprietary ST-LINK, or the free replacement. 51 | 52 | An already unlocked RS41 does not require `make erase` before programming. Always remember to press the power button after inserting batteries, or the MCU will not be powered for programming. 53 | 54 | ## Usage 55 | * Program as above. 56 | * Once batteries are inserted, press the power button to start transmissions. 57 | * Remove batteries to stop transmissions. 58 | 59 | # Power Consumption Notes 60 | Power consumption of the various peripherals is approximately: 61 | * uC + other quiescent power usage: ~100 mW 62 | * Radio: ~170 mW (20mW TX Power) 63 | * GPS (Acquisition/Tracking Mode): ~210 mW 64 | 65 | In the case of a stationary radio fox, there isn't much point enabling the GPS after the initial position fix, so we turn it off. This almost doubles our battery life... 66 | 67 | ## Runtime Estimate 68 | Achieved battery life will depend on your battery chemistry and transmit duty cycle. As a pessimistic estimate (assume 100% duty cycle, GPS disabled), we can state that the power consumption of the RS41 is 270mW. 69 | 70 | Using 2x [AA Lithium cells](http://data.energizer.com/pdfs/l91.pdf) (~3Ah @ 3V = 9 Wh), we have a runtime of approximately 33 hours. 71 | Using 2x [Alkaline AAs](http://data.energizer.com/pdfs/e91.pdf), (~2.5Ah @ 3V = 7.5 Wh), the expected runtime is 27 hours (if operating continuously), though note that the discharge curve of the batteries is quite different to the Lithiums, and the low-voltage thresholds will need to be adjusted appropriately. 72 | 73 | ### Runtime Actuals 74 | * 2x Energizer Industrial Alkaline AA - 20mW TX, On = 10 seconds, Off = 10 seconds, Low Voltage Cutout = 0.5V - Runtime: 36 hours. 75 | * 2x Energizer Lithium AA - 20mW TX, On = 10 seconds, Off = 10 seconds, Low Voltage Cutout = 0.5V - Runtime: ?? 76 | -------------------------------------------------------------------------------- /RS41HUP.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darksidelemm/RS41FOX/9a4e4137032302171b62b3976e8ceb72193e5ecc/RS41HUP.elf -------------------------------------------------------------------------------- /arm-gcc-link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | /* Internal Memory Map*/ 3 | MEMORY 4 | { 5 | rom (rx) : ORIGIN = 0x08000000, LENGTH = 0x00010000 6 | ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00002000 7 | } 8 | 9 | _eram = 0x20000000 + 0x00002000; 10 | SECTIONS 11 | { 12 | .text : 13 | { 14 | KEEP(*(.isr_vector)) 15 | *(.text*) 16 | 17 | KEEP(*(.init)) 18 | KEEP(*(.fini)) 19 | 20 | /* .ctors */ 21 | *crtbegin.o(.ctors) 22 | *crtbegin?.o(.ctors) 23 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) 24 | *(SORT(.ctors.*)) 25 | *(.ctors) 26 | 27 | /* .dtors */ 28 | *crtbegin.o(.dtors) 29 | *crtbegin?.o(.dtors) 30 | *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) 31 | *(SORT(.dtors.*)) 32 | *(.dtors) 33 | 34 | *(.rodata*) 35 | 36 | KEEP(*(.eh_fram e*)) 37 | } > rom 38 | 39 | .ARM.extab : 40 | { 41 | *(.ARM.extab* .gnu.linkonce.armextab.*) 42 | } > rom 43 | 44 | __exidx_start = .; 45 | .ARM.exidx : 46 | { 47 | *(.ARM.exidx* .gnu.linkonce.armexidx.*) 48 | } > rom 49 | __exidx_end = .; 50 | __etext = .; 51 | 52 | /* _sidata is used in coide startup code */ 53 | _sidata = __etext; 54 | 55 | .data : AT (__etext) 56 | { 57 | __data_start__ = .; 58 | 59 | /* _sdata is used in coide startup code */ 60 | _sdata = __data_start__; 61 | 62 | *(vtable) 63 | *(.data*) 64 | 65 | . = ALIGN(4); 66 | /* preinit data */ 67 | PROVIDE_HIDDEN (__preinit_array_start = .); 68 | KEEP(*(.preinit_array)) 69 | PROVIDE_HIDDEN (__preinit_array_end = .); 70 | 71 | . = ALIGN(4); 72 | /* init data */ 73 | PROVIDE_HIDDEN (__init_array_start = .); 74 | KEEP(*(SORT(.init_array.*))) 75 | KEEP(*(.init_array)) 76 | PROVIDE_HIDDEN (__init_array_end = .); 77 | 78 | . = ALIGN(4); 79 | /* finit data */ 80 | PROVIDE_HIDDEN (__fini_array_start = .); 81 | KEEP(*(SORT(.fini_array.*))) 82 | KEEP(*(.fini_array)) 83 | PROVIDE_HIDDEN (__fini_array_end = .); 84 | 85 | KEEP(*(.jcr*)) 86 | . = ALIGN(4); 87 | /* All data end */ 88 | __data_end__ = .; 89 | 90 | /* _edata is used in coide startup code */ 91 | _edata = __data_end__; 92 | } > ram 93 | 94 | .bss : 95 | { 96 | . = ALIGN(4); 97 | __bss_start__ = .; 98 | _sbss = __bss_start__; 99 | *(.bss*) 100 | *(COMMON) 101 | . = ALIGN(4); 102 | __bss_end__ = .; 103 | _ebss = __bss_end__; 104 | } > ram 105 | 106 | .heap (COPY): 107 | { 108 | __end__ = .; 109 | _end = __end__; 110 | end = __end__; 111 | *(.heap*) 112 | __HeapLimit = .; 113 | } > ram 114 | 115 | /* .stack_dummy section doesn't contains any symbols. It is only 116 | * used for linker to calculate size of stack sections, and assign 117 | * values to stack symbols later */ 118 | .co_stack (NOLOAD): 119 | { 120 | . = ALIGN(8); 121 | *(.co_stack .co_stack.*) 122 | } > ram 123 | 124 | /* Set stack top to end of ram , and stack limit move down by 125 | * size of stack_dummy section */ 126 | __StackTop = ORIGIN(ram ) + LENGTH(ram ); 127 | __StackLimit = __StackTop - SIZEOF(.co_stack); 128 | PROVIDE(__stack = __StackTop); 129 | 130 | /* Check if data + heap + stack exceeds ram limit */ 131 | ASSERT(__StackLimit >= __HeapLimit, "region ram overflowed with stack") 132 | } -------------------------------------------------------------------------------- /cmake-clean: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | rm -f CMakeCache.txt 4 | rm -f RS41HUP.bin 5 | rm -f RS41HUP.hex 6 | rm -f RS41HUP.map 7 | rm -f cmake_install.cmake 8 | rm -f Makefile 9 | rm -rf CMakeFiles/* 10 | -------------------------------------------------------------------------------- /cmsis/.readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /cmsis/core_cmFunc.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file core_cmFunc.h 3 | * @brief CMSIS Cortex-M Core Function Access Header File 4 | * @version V3.01 5 | * @date 06. March 2012 6 | * 7 | * @note 8 | * Copyright (C) 2009-2012 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 | #ifndef __CORE_CMFUNC_H 25 | #define __CORE_CMFUNC_H 26 | 27 | 28 | /* ########################### Core Function Access ########################### */ 29 | /** \ingroup CMSIS_Core_FunctionInterface 30 | \defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions 31 | @{ 32 | */ 33 | 34 | #if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ 35 | /* ARM armcc specific functions */ 36 | 37 | #if (__ARMCC_VERSION < 400677) 38 | #error "Please use ARM Compiler Toolchain V4.0.677 or later!" 39 | #endif 40 | 41 | /* intrinsic void __enable_irq(); */ 42 | /* intrinsic void __disable_irq(); */ 43 | 44 | /** \brief Get Control Register 45 | 46 | This function returns the content of the Control Register. 47 | 48 | \return Control Register value 49 | */ 50 | __STATIC_INLINE uint32_t __get_CONTROL(void) 51 | { 52 | register uint32_t __regControl __ASM("control"); 53 | return(__regControl); 54 | } 55 | 56 | 57 | /** \brief Set Control Register 58 | 59 | This function writes the given value to the Control Register. 60 | 61 | \param [in] control Control Register value to set 62 | */ 63 | __STATIC_INLINE void __set_CONTROL(uint32_t control) 64 | { 65 | register uint32_t __regControl __ASM("control"); 66 | __regControl = control; 67 | } 68 | 69 | 70 | /** \brief Get IPSR Register 71 | 72 | This function returns the content of the IPSR Register. 73 | 74 | \return IPSR Register value 75 | */ 76 | __STATIC_INLINE uint32_t __get_IPSR(void) 77 | { 78 | register uint32_t __regIPSR __ASM("ipsr"); 79 | return(__regIPSR); 80 | } 81 | 82 | 83 | /** \brief Get APSR Register 84 | 85 | This function returns the content of the APSR Register. 86 | 87 | \return APSR Register value 88 | */ 89 | __STATIC_INLINE uint32_t __get_APSR(void) 90 | { 91 | register uint32_t __regAPSR __ASM("apsr"); 92 | return(__regAPSR); 93 | } 94 | 95 | 96 | /** \brief Get xPSR Register 97 | 98 | This function returns the content of the xPSR Register. 99 | 100 | \return xPSR Register value 101 | */ 102 | __STATIC_INLINE uint32_t __get_xPSR(void) 103 | { 104 | register uint32_t __regXPSR __ASM("xpsr"); 105 | return(__regXPSR); 106 | } 107 | 108 | 109 | /** \brief Get Process Stack Pointer 110 | 111 | This function returns the current value of the Process Stack Pointer (PSP). 112 | 113 | \return PSP Register value 114 | */ 115 | __STATIC_INLINE uint32_t __get_PSP(void) 116 | { 117 | register uint32_t __regProcessStackPointer __ASM("psp"); 118 | return(__regProcessStackPointer); 119 | } 120 | 121 | 122 | /** \brief Set Process Stack Pointer 123 | 124 | This function assigns the given value to the Process Stack Pointer (PSP). 125 | 126 | \param [in] topOfProcStack Process Stack Pointer value to set 127 | */ 128 | __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) 129 | { 130 | register uint32_t __regProcessStackPointer __ASM("psp"); 131 | __regProcessStackPointer = topOfProcStack; 132 | } 133 | 134 | 135 | /** \brief Get Main Stack Pointer 136 | 137 | This function returns the current value of the Main Stack Pointer (MSP). 138 | 139 | \return MSP Register value 140 | */ 141 | __STATIC_INLINE uint32_t __get_MSP(void) 142 | { 143 | register uint32_t __regMainStackPointer __ASM("msp"); 144 | return(__regMainStackPointer); 145 | } 146 | 147 | 148 | /** \brief Set Main Stack Pointer 149 | 150 | This function assigns the given value to the Main Stack Pointer (MSP). 151 | 152 | \param [in] topOfMainStack Main Stack Pointer value to set 153 | */ 154 | __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) 155 | { 156 | register uint32_t __regMainStackPointer __ASM("msp"); 157 | __regMainStackPointer = topOfMainStack; 158 | } 159 | 160 | 161 | /** \brief Get Priority Mask 162 | 163 | This function returns the current state of the priority mask bit from the Priority Mask Register. 164 | 165 | \return Priority Mask value 166 | */ 167 | __STATIC_INLINE uint32_t __get_PRIMASK(void) 168 | { 169 | register uint32_t __regPriMask __ASM("primask"); 170 | return(__regPriMask); 171 | } 172 | 173 | 174 | /** \brief Set Priority Mask 175 | 176 | This function assigns the given value to the Priority Mask Register. 177 | 178 | \param [in] priMask Priority Mask 179 | */ 180 | __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) 181 | { 182 | register uint32_t __regPriMask __ASM("primask"); 183 | __regPriMask = (priMask); 184 | } 185 | 186 | 187 | #if (__CORTEX_M >= 0x03) 188 | 189 | /** \brief Enable FIQ 190 | 191 | This function enables FIQ interrupts by clearing the F-bit in the CPSR. 192 | Can only be executed in Privileged modes. 193 | */ 194 | #define __enable_fault_irq __enable_fiq 195 | 196 | 197 | /** \brief Disable FIQ 198 | 199 | This function disables FIQ interrupts by setting the F-bit in the CPSR. 200 | Can only be executed in Privileged modes. 201 | */ 202 | #define __disable_fault_irq __disable_fiq 203 | 204 | 205 | /** \brief Get Base Priority 206 | 207 | This function returns the current value of the Base Priority register. 208 | 209 | \return Base Priority register value 210 | */ 211 | __STATIC_INLINE uint32_t __get_BASEPRI(void) 212 | { 213 | register uint32_t __regBasePri __ASM("basepri"); 214 | return(__regBasePri); 215 | } 216 | 217 | 218 | /** \brief Set Base Priority 219 | 220 | This function assigns the given value to the Base Priority register. 221 | 222 | \param [in] basePri Base Priority value to set 223 | */ 224 | __STATIC_INLINE void __set_BASEPRI(uint32_t basePri) 225 | { 226 | register uint32_t __regBasePri __ASM("basepri"); 227 | __regBasePri = (basePri & 0xff); 228 | } 229 | 230 | 231 | /** \brief Get Fault Mask 232 | 233 | This function returns the current value of the Fault Mask register. 234 | 235 | \return Fault Mask register value 236 | */ 237 | __STATIC_INLINE uint32_t __get_FAULTMASK(void) 238 | { 239 | register uint32_t __regFaultMask __ASM("faultmask"); 240 | return(__regFaultMask); 241 | } 242 | 243 | 244 | /** \brief Set Fault Mask 245 | 246 | This function assigns the given value to the Fault Mask register. 247 | 248 | \param [in] faultMask Fault Mask value to set 249 | */ 250 | __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) 251 | { 252 | register uint32_t __regFaultMask __ASM("faultmask"); 253 | __regFaultMask = (faultMask & (uint32_t)1); 254 | } 255 | 256 | #endif /* (__CORTEX_M >= 0x03) */ 257 | 258 | 259 | #if (__CORTEX_M == 0x04) 260 | 261 | /** \brief Get FPSCR 262 | 263 | This function returns the current value of the Floating Point Status/Control register. 264 | 265 | \return Floating Point Status/Control register value 266 | */ 267 | __STATIC_INLINE uint32_t __get_FPSCR(void) 268 | { 269 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 270 | register uint32_t __regfpscr __ASM("fpscr"); 271 | return(__regfpscr); 272 | #else 273 | return(0); 274 | #endif 275 | } 276 | 277 | 278 | /** \brief Set FPSCR 279 | 280 | This function assigns the given value to the Floating Point Status/Control register. 281 | 282 | \param [in] fpscr Floating Point Status/Control value to set 283 | */ 284 | __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) 285 | { 286 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 287 | register uint32_t __regfpscr __ASM("fpscr"); 288 | __regfpscr = (fpscr); 289 | #endif 290 | } 291 | 292 | #endif /* (__CORTEX_M == 0x04) */ 293 | 294 | 295 | #elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ 296 | /* IAR iccarm specific functions */ 297 | 298 | #include 299 | 300 | 301 | #elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ 302 | /* TI CCS specific functions */ 303 | 304 | #include 305 | 306 | 307 | #elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ 308 | /* GNU gcc specific functions */ 309 | 310 | /** \brief Enable IRQ Interrupts 311 | 312 | This function enables IRQ interrupts by clearing the I-bit in the CPSR. 313 | Can only be executed in Privileged modes. 314 | */ 315 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_irq(void) 316 | { 317 | __ASM volatile ("cpsie i"); 318 | } 319 | 320 | 321 | /** \brief Disable IRQ Interrupts 322 | 323 | This function disables IRQ interrupts by setting the I-bit in the CPSR. 324 | Can only be executed in Privileged modes. 325 | */ 326 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_irq(void) 327 | { 328 | __ASM volatile ("cpsid i"); 329 | } 330 | 331 | 332 | /** \brief Get Control Register 333 | 334 | This function returns the content of the Control Register. 335 | 336 | \return Control Register value 337 | */ 338 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_CONTROL(void) 339 | { 340 | uint32_t result; 341 | 342 | __ASM volatile ("MRS %0, control" : "=r" (result) ); 343 | return(result); 344 | } 345 | 346 | 347 | /** \brief Set Control Register 348 | 349 | This function writes the given value to the Control Register. 350 | 351 | \param [in] control Control Register value to set 352 | */ 353 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_CONTROL(uint32_t control) 354 | { 355 | __ASM volatile ("MSR control, %0" : : "r" (control) ); 356 | } 357 | 358 | 359 | /** \brief Get IPSR Register 360 | 361 | This function returns the content of the IPSR Register. 362 | 363 | \return IPSR Register value 364 | */ 365 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_IPSR(void) 366 | { 367 | uint32_t result; 368 | 369 | __ASM volatile ("MRS %0, ipsr" : "=r" (result) ); 370 | return(result); 371 | } 372 | 373 | 374 | /** \brief Get APSR Register 375 | 376 | This function returns the content of the APSR Register. 377 | 378 | \return APSR Register value 379 | */ 380 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_APSR(void) 381 | { 382 | uint32_t result; 383 | 384 | __ASM volatile ("MRS %0, apsr" : "=r" (result) ); 385 | return(result); 386 | } 387 | 388 | 389 | /** \brief Get xPSR Register 390 | 391 | This function returns the content of the xPSR Register. 392 | 393 | \return xPSR Register value 394 | */ 395 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_xPSR(void) 396 | { 397 | uint32_t result; 398 | 399 | __ASM volatile ("MRS %0, xpsr" : "=r" (result) ); 400 | return(result); 401 | } 402 | 403 | 404 | /** \brief Get Process Stack Pointer 405 | 406 | This function returns the current value of the Process Stack Pointer (PSP). 407 | 408 | \return PSP Register value 409 | */ 410 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PSP(void) 411 | { 412 | register uint32_t result; 413 | 414 | __ASM volatile ("MRS %0, psp\n" : "=r" (result) ); 415 | return(result); 416 | } 417 | 418 | 419 | /** \brief Set Process Stack Pointer 420 | 421 | This function assigns the given value to the Process Stack Pointer (PSP). 422 | 423 | \param [in] topOfProcStack Process Stack Pointer value to set 424 | */ 425 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PSP(uint32_t topOfProcStack) 426 | { 427 | __ASM volatile ("MSR psp, %0\n" : : "r" (topOfProcStack) ); 428 | } 429 | 430 | 431 | /** \brief Get Main Stack Pointer 432 | 433 | This function returns the current value of the Main Stack Pointer (MSP). 434 | 435 | \return MSP Register value 436 | */ 437 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_MSP(void) 438 | { 439 | register uint32_t result; 440 | 441 | __ASM volatile ("MRS %0, msp\n" : "=r" (result) ); 442 | return(result); 443 | } 444 | 445 | 446 | /** \brief Set Main Stack Pointer 447 | 448 | This function assigns the given value to the Main Stack Pointer (MSP). 449 | 450 | \param [in] topOfMainStack Main Stack Pointer value to set 451 | */ 452 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_MSP(uint32_t topOfMainStack) 453 | { 454 | __ASM volatile ("MSR msp, %0\n" : : "r" (topOfMainStack) ); 455 | } 456 | 457 | 458 | /** \brief Get Priority Mask 459 | 460 | This function returns the current state of the priority mask bit from the Priority Mask Register. 461 | 462 | \return Priority Mask value 463 | */ 464 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_PRIMASK(void) 465 | { 466 | uint32_t result; 467 | 468 | __ASM volatile ("MRS %0, primask" : "=r" (result) ); 469 | return(result); 470 | } 471 | 472 | 473 | /** \brief Set Priority Mask 474 | 475 | This function assigns the given value to the Priority Mask Register. 476 | 477 | \param [in] priMask Priority Mask 478 | */ 479 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_PRIMASK(uint32_t priMask) 480 | { 481 | __ASM volatile ("MSR primask, %0" : : "r" (priMask) ); 482 | } 483 | 484 | 485 | #if (__CORTEX_M >= 0x03) 486 | 487 | /** \brief Enable FIQ 488 | 489 | This function enables FIQ interrupts by clearing the F-bit in the CPSR. 490 | Can only be executed in Privileged modes. 491 | */ 492 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __enable_fault_irq(void) 493 | { 494 | __ASM volatile ("cpsie f"); 495 | } 496 | 497 | 498 | /** \brief Disable FIQ 499 | 500 | This function disables FIQ interrupts by setting the F-bit in the CPSR. 501 | Can only be executed in Privileged modes. 502 | */ 503 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __disable_fault_irq(void) 504 | { 505 | __ASM volatile ("cpsid f"); 506 | } 507 | 508 | 509 | /** \brief Get Base Priority 510 | 511 | This function returns the current value of the Base Priority register. 512 | 513 | \return Base Priority register value 514 | */ 515 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void) 516 | { 517 | uint32_t result; 518 | 519 | __ASM volatile ("MRS %0, basepri_max" : "=r" (result) ); 520 | return(result); 521 | } 522 | 523 | 524 | /** \brief Set Base Priority 525 | 526 | This function assigns the given value to the Base Priority register. 527 | 528 | \param [in] basePri Base Priority value to set 529 | */ 530 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_BASEPRI(uint32_t value) 531 | { 532 | __ASM volatile ("MSR basepri, %0" : : "r" (value) ); 533 | } 534 | 535 | 536 | /** \brief Get Fault Mask 537 | 538 | This function returns the current value of the Fault Mask register. 539 | 540 | \return Fault Mask register value 541 | */ 542 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FAULTMASK(void) 543 | { 544 | uint32_t result; 545 | 546 | __ASM volatile ("MRS %0, faultmask" : "=r" (result) ); 547 | return(result); 548 | } 549 | 550 | 551 | /** \brief Set Fault Mask 552 | 553 | This function assigns the given value to the Fault Mask register. 554 | 555 | \param [in] faultMask Fault Mask value to set 556 | */ 557 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask) 558 | { 559 | __ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) ); 560 | } 561 | 562 | #endif /* (__CORTEX_M >= 0x03) */ 563 | 564 | 565 | #if (__CORTEX_M == 0x04) 566 | 567 | /** \brief Get FPSCR 568 | 569 | This function returns the current value of the Floating Point Status/Control register. 570 | 571 | \return Floating Point Status/Control register value 572 | */ 573 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_FPSCR(void) 574 | { 575 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 576 | uint32_t result; 577 | 578 | __ASM volatile ("VMRS %0, fpscr" : "=r" (result) ); 579 | return(result); 580 | #else 581 | return(0); 582 | #endif 583 | } 584 | 585 | 586 | /** \brief Set FPSCR 587 | 588 | This function assigns the given value to the Floating Point Status/Control register. 589 | 590 | \param [in] fpscr Floating Point Status/Control value to set 591 | */ 592 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __set_FPSCR(uint32_t fpscr) 593 | { 594 | #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) 595 | __ASM volatile ("VMSR fpscr, %0" : : "r" (fpscr) ); 596 | #endif 597 | } 598 | 599 | #endif /* (__CORTEX_M == 0x04) */ 600 | 601 | 602 | #elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ 603 | /* TASKING carm specific functions */ 604 | 605 | /* 606 | * The CMSIS functions have been implemented as intrinsics in the compiler. 607 | * Please use "carm -?i" to get an up to date list of all instrinsics, 608 | * Including the CMSIS ones. 609 | */ 610 | 611 | #endif 612 | 613 | /*@} end of CMSIS_Core_RegAccFunctions */ 614 | 615 | 616 | #endif /* __CORE_CMFUNC_H */ 617 | -------------------------------------------------------------------------------- /cmsis/core_cmInstr.h: -------------------------------------------------------------------------------- 1 | /**************************************************************************//** 2 | * @file core_cmInstr.h 3 | * @brief CMSIS Cortex-M Core Instruction Access Header File 4 | * @version V3.01 5 | * @date 06. March 2012 6 | * 7 | * @note 8 | * Copyright (C) 2009-2012 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 | #ifndef __CORE_CMINSTR_H 25 | #define __CORE_CMINSTR_H 26 | 27 | 28 | /* ########################## Core Instruction Access ######################### */ 29 | /** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface 30 | Access to dedicated instructions 31 | @{ 32 | */ 33 | 34 | #if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/ 35 | /* ARM armcc specific functions */ 36 | 37 | #if (__ARMCC_VERSION < 400677) 38 | #error "Please use ARM Compiler Toolchain V4.0.677 or later!" 39 | #endif 40 | 41 | 42 | /** \brief No Operation 43 | 44 | No Operation does nothing. This instruction can be used for code alignment purposes. 45 | */ 46 | #define __NOP __nop 47 | 48 | 49 | /** \brief Wait For Interrupt 50 | 51 | Wait For Interrupt is a hint instruction that suspends execution 52 | until one of a number of events occurs. 53 | */ 54 | #define __WFI __wfi 55 | 56 | 57 | /** \brief Wait For Event 58 | 59 | Wait For Event is a hint instruction that permits the processor to enter 60 | a low-power state until one of a number of events occurs. 61 | */ 62 | #define __WFE __wfe 63 | 64 | 65 | /** \brief Send Event 66 | 67 | Send Event is a hint instruction. It causes an event to be signaled to the CPU. 68 | */ 69 | #define __SEV __sev 70 | 71 | 72 | /** \brief Instruction Synchronization Barrier 73 | 74 | Instruction Synchronization Barrier flushes the pipeline in the processor, 75 | so that all instructions following the ISB are fetched from cache or 76 | memory, after the instruction has been completed. 77 | */ 78 | #define __ISB() __isb(0xF) 79 | 80 | 81 | /** \brief Data Synchronization Barrier 82 | 83 | This function acts as a special kind of Data Memory Barrier. 84 | It completes when all explicit memory accesses before this instruction complete. 85 | */ 86 | #define __DSB() __dsb(0xF) 87 | 88 | 89 | /** \brief Data Memory Barrier 90 | 91 | This function ensures the apparent order of the explicit memory operations before 92 | and after the instruction, without ensuring their completion. 93 | */ 94 | #define __DMB() __dmb(0xF) 95 | 96 | 97 | /** \brief Reverse byte order (32 bit) 98 | 99 | This function reverses the byte order in integer value. 100 | 101 | \param [in] value Value to reverse 102 | \return Reversed value 103 | */ 104 | #define __REV __rev 105 | 106 | 107 | /** \brief Reverse byte order (16 bit) 108 | 109 | This function reverses the byte order in two unsigned short values. 110 | 111 | \param [in] value Value to reverse 112 | \return Reversed value 113 | */ 114 | __attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value) 115 | { 116 | rev16 r0, r0 117 | bx lr 118 | } 119 | 120 | 121 | /** \brief Reverse byte order in signed short value 122 | 123 | This function reverses the byte order in a signed short value with sign extension to integer. 124 | 125 | \param [in] value Value to reverse 126 | \return Reversed value 127 | */ 128 | __attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int32_t __REVSH(int32_t value) 129 | { 130 | revsh r0, r0 131 | bx lr 132 | } 133 | 134 | 135 | /** \brief Rotate Right in unsigned value (32 bit) 136 | 137 | This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. 138 | 139 | \param [in] value Value to rotate 140 | \param [in] value Number of Bits to rotate 141 | \return Rotated value 142 | */ 143 | #define __ROR __ror 144 | 145 | 146 | #if (__CORTEX_M >= 0x03) 147 | 148 | /** \brief Reverse bit order of value 149 | 150 | This function reverses the bit order of the given value. 151 | 152 | \param [in] value Value to reverse 153 | \return Reversed value 154 | */ 155 | #define __RBIT __rbit 156 | 157 | 158 | /** \brief LDR Exclusive (8 bit) 159 | 160 | This function performs a exclusive LDR command for 8 bit value. 161 | 162 | \param [in] ptr Pointer to data 163 | \return value of type uint8_t at (*ptr) 164 | */ 165 | #define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr)) 166 | 167 | 168 | /** \brief LDR Exclusive (16 bit) 169 | 170 | This function performs a exclusive LDR command for 16 bit values. 171 | 172 | \param [in] ptr Pointer to data 173 | \return value of type uint16_t at (*ptr) 174 | */ 175 | #define __LDREXH(ptr) ((uint16_t) __ldrex(ptr)) 176 | 177 | 178 | /** \brief LDR Exclusive (32 bit) 179 | 180 | This function performs a exclusive LDR command for 32 bit values. 181 | 182 | \param [in] ptr Pointer to data 183 | \return value of type uint32_t at (*ptr) 184 | */ 185 | #define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr)) 186 | 187 | 188 | /** \brief STR Exclusive (8 bit) 189 | 190 | This function performs a exclusive STR command for 8 bit values. 191 | 192 | \param [in] value Value to store 193 | \param [in] ptr Pointer to location 194 | \return 0 Function succeeded 195 | \return 1 Function failed 196 | */ 197 | #define __STREXB(value, ptr) __strex(value, ptr) 198 | 199 | 200 | /** \brief STR Exclusive (16 bit) 201 | 202 | This function performs a exclusive STR command for 16 bit values. 203 | 204 | \param [in] value Value to store 205 | \param [in] ptr Pointer to location 206 | \return 0 Function succeeded 207 | \return 1 Function failed 208 | */ 209 | #define __STREXH(value, ptr) __strex(value, ptr) 210 | 211 | 212 | /** \brief STR Exclusive (32 bit) 213 | 214 | This function performs a exclusive STR command for 32 bit values. 215 | 216 | \param [in] value Value to store 217 | \param [in] ptr Pointer to location 218 | \return 0 Function succeeded 219 | \return 1 Function failed 220 | */ 221 | #define __STREXW(value, ptr) __strex(value, ptr) 222 | 223 | 224 | /** \brief Remove the exclusive lock 225 | 226 | This function removes the exclusive lock which is created by LDREX. 227 | 228 | */ 229 | #define __CLREX __clrex 230 | 231 | 232 | /** \brief Signed Saturate 233 | 234 | This function saturates a signed value. 235 | 236 | \param [in] value Value to be saturated 237 | \param [in] sat Bit position to saturate to (1..32) 238 | \return Saturated value 239 | */ 240 | #define __SSAT __ssat 241 | 242 | 243 | /** \brief Unsigned Saturate 244 | 245 | This function saturates an unsigned value. 246 | 247 | \param [in] value Value to be saturated 248 | \param [in] sat Bit position to saturate to (0..31) 249 | \return Saturated value 250 | */ 251 | #define __USAT __usat 252 | 253 | 254 | /** \brief Count leading zeros 255 | 256 | This function counts the number of leading zeros of a data value. 257 | 258 | \param [in] value Value to count the leading zeros 259 | \return number of leading zeros in value 260 | */ 261 | #define __CLZ __clz 262 | 263 | #endif /* (__CORTEX_M >= 0x03) */ 264 | 265 | 266 | 267 | #elif defined ( __ICCARM__ ) /*------------------ ICC Compiler -------------------*/ 268 | /* IAR iccarm specific functions */ 269 | 270 | #include 271 | 272 | 273 | #elif defined ( __TMS470__ ) /*---------------- TI CCS Compiler ------------------*/ 274 | /* TI CCS specific functions */ 275 | 276 | #include 277 | 278 | 279 | #elif defined ( __GNUC__ ) /*------------------ GNU Compiler ---------------------*/ 280 | /* GNU gcc specific functions */ 281 | 282 | /** \brief No Operation 283 | 284 | No Operation does nothing. This instruction can be used for code alignment purposes. 285 | */ 286 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __NOP(void) 287 | { 288 | __ASM volatile ("nop"); 289 | } 290 | 291 | 292 | /** \brief Wait For Interrupt 293 | 294 | Wait For Interrupt is a hint instruction that suspends execution 295 | until one of a number of events occurs. 296 | */ 297 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __WFI(void) 298 | { 299 | __ASM volatile ("wfi"); 300 | } 301 | 302 | 303 | /** \brief Wait For Event 304 | 305 | Wait For Event is a hint instruction that permits the processor to enter 306 | a low-power state until one of a number of events occurs. 307 | */ 308 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __WFE(void) 309 | { 310 | __ASM volatile ("wfe"); 311 | } 312 | 313 | 314 | /** \brief Send Event 315 | 316 | Send Event is a hint instruction. It causes an event to be signaled to the CPU. 317 | */ 318 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __SEV(void) 319 | { 320 | __ASM volatile ("sev"); 321 | } 322 | 323 | 324 | /** \brief Instruction Synchronization Barrier 325 | 326 | Instruction Synchronization Barrier flushes the pipeline in the processor, 327 | so that all instructions following the ISB are fetched from cache or 328 | memory, after the instruction has been completed. 329 | */ 330 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __ISB(void) 331 | { 332 | __ASM volatile ("isb"); 333 | } 334 | 335 | 336 | /** \brief Data Synchronization Barrier 337 | 338 | This function acts as a special kind of Data Memory Barrier. 339 | It completes when all explicit memory accesses before this instruction complete. 340 | */ 341 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __DSB(void) 342 | { 343 | __ASM volatile ("dsb"); 344 | } 345 | 346 | 347 | /** \brief Data Memory Barrier 348 | 349 | This function ensures the apparent order of the explicit memory operations before 350 | and after the instruction, without ensuring their completion. 351 | */ 352 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __DMB(void) 353 | { 354 | __ASM volatile ("dmb"); 355 | } 356 | 357 | 358 | /** \brief Reverse byte order (32 bit) 359 | 360 | This function reverses the byte order in integer value. 361 | 362 | \param [in] value Value to reverse 363 | \return Reversed value 364 | */ 365 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV(uint32_t value) 366 | { 367 | uint32_t result; 368 | 369 | __ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) ); 370 | return(result); 371 | } 372 | 373 | 374 | /** \brief Reverse byte order (16 bit) 375 | 376 | This function reverses the byte order in two unsigned short values. 377 | 378 | \param [in] value Value to reverse 379 | \return Reversed value 380 | */ 381 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __REV16(uint32_t value) 382 | { 383 | uint32_t result; 384 | 385 | __ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) ); 386 | return(result); 387 | } 388 | 389 | 390 | /** \brief Reverse byte order in signed short value 391 | 392 | This function reverses the byte order in a signed short value with sign extension to integer. 393 | 394 | \param [in] value Value to reverse 395 | \return Reversed value 396 | */ 397 | __attribute__( ( always_inline ) ) __STATIC_INLINE int32_t __REVSH(int32_t value) 398 | { 399 | uint32_t result; 400 | 401 | __ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) ); 402 | return(result); 403 | } 404 | 405 | 406 | /** \brief Rotate Right in unsigned value (32 bit) 407 | 408 | This function Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits. 409 | 410 | \param [in] value Value to rotate 411 | \param [in] value Number of Bits to rotate 412 | \return Rotated value 413 | */ 414 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __ROR(uint32_t op1, uint32_t op2) 415 | { 416 | 417 | __ASM volatile ("ror %0, %0, %1" : "+r" (op1) : "r" (op2) ); 418 | return(op1); 419 | } 420 | 421 | 422 | #if (__CORTEX_M >= 0x03) 423 | 424 | /** \brief Reverse bit order of value 425 | 426 | This function reverses the bit order of the given value. 427 | 428 | \param [in] value Value to reverse 429 | \return Reversed value 430 | */ 431 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __RBIT(uint32_t value) 432 | { 433 | uint32_t result; 434 | 435 | __ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) ); 436 | return(result); 437 | } 438 | 439 | 440 | /** \brief LDR Exclusive (8 bit) 441 | 442 | This function performs a exclusive LDR command for 8 bit value. 443 | 444 | \param [in] ptr Pointer to data 445 | \return value of type uint8_t at (*ptr) 446 | */ 447 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __LDREXB(volatile uint8_t *addr) 448 | { 449 | uint8_t result; 450 | 451 | __ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) ); 452 | return(result); 453 | } 454 | 455 | 456 | /** \brief LDR Exclusive (16 bit) 457 | 458 | This function performs a exclusive LDR command for 16 bit values. 459 | 460 | \param [in] ptr Pointer to data 461 | \return value of type uint16_t at (*ptr) 462 | */ 463 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint16_t __LDREXH(volatile uint16_t *addr) 464 | { 465 | uint16_t result; 466 | 467 | __ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) ); 468 | return(result); 469 | } 470 | 471 | 472 | /** \brief LDR Exclusive (32 bit) 473 | 474 | This function performs a exclusive LDR command for 32 bit values. 475 | 476 | \param [in] ptr Pointer to data 477 | \return value of type uint32_t at (*ptr) 478 | */ 479 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __LDREXW(volatile uint32_t *addr) 480 | { 481 | uint32_t result; 482 | 483 | __ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) ); 484 | return(result); 485 | } 486 | 487 | 488 | /** \brief STR Exclusive (8 bit) 489 | 490 | This function performs a exclusive STR command for 8 bit values. 491 | 492 | \param [in] value Value to store 493 | \param [in] ptr Pointer to location 494 | \return 0 Function succeeded 495 | \return 1 Function failed 496 | */ 497 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXB(uint8_t value, volatile uint8_t *addr) 498 | { 499 | uint32_t result; 500 | 501 | __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); 502 | return(result); 503 | } 504 | 505 | 506 | /** \brief STR Exclusive (16 bit) 507 | 508 | This function performs a exclusive STR command for 16 bit values. 509 | 510 | \param [in] value Value to store 511 | \param [in] ptr Pointer to location 512 | \return 0 Function succeeded 513 | \return 1 Function failed 514 | */ 515 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXH(uint16_t value, volatile uint16_t *addr) 516 | { 517 | uint32_t result; 518 | 519 | __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); 520 | return(result); 521 | } 522 | 523 | 524 | /** \brief STR Exclusive (32 bit) 525 | 526 | This function performs a exclusive STR command for 32 bit values. 527 | 528 | \param [in] value Value to store 529 | \param [in] ptr Pointer to location 530 | \return 0 Function succeeded 531 | \return 1 Function failed 532 | */ 533 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __STREXW(uint32_t value, volatile uint32_t *addr) 534 | { 535 | uint32_t result; 536 | 537 | __ASM volatile ("strex %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) ); 538 | return(result); 539 | } 540 | 541 | 542 | /** \brief Remove the exclusive lock 543 | 544 | This function removes the exclusive lock which is created by LDREX. 545 | 546 | */ 547 | __attribute__( ( always_inline ) ) __STATIC_INLINE void __CLREX(void) 548 | { 549 | __ASM volatile ("clrex"); 550 | } 551 | 552 | 553 | /** \brief Signed Saturate 554 | 555 | This function saturates a signed value. 556 | 557 | \param [in] value Value to be saturated 558 | \param [in] sat Bit position to saturate to (1..32) 559 | \return Saturated value 560 | */ 561 | #define __SSAT(ARG1,ARG2) \ 562 | ({ \ 563 | uint32_t __RES, __ARG1 = (ARG1); \ 564 | __ASM ("ssat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 565 | __RES; \ 566 | }) 567 | 568 | 569 | /** \brief Unsigned Saturate 570 | 571 | This function saturates an unsigned value. 572 | 573 | \param [in] value Value to be saturated 574 | \param [in] sat Bit position to saturate to (0..31) 575 | \return Saturated value 576 | */ 577 | #define __USAT(ARG1,ARG2) \ 578 | ({ \ 579 | uint32_t __RES, __ARG1 = (ARG1); \ 580 | __ASM ("usat %0, %1, %2" : "=r" (__RES) : "I" (ARG2), "r" (__ARG1) ); \ 581 | __RES; \ 582 | }) 583 | 584 | 585 | /** \brief Count leading zeros 586 | 587 | This function counts the number of leading zeros of a data value. 588 | 589 | \param [in] value Value to count the leading zeros 590 | \return number of leading zeros in value 591 | */ 592 | __attribute__( ( always_inline ) ) __STATIC_INLINE uint8_t __CLZ(uint32_t value) 593 | { 594 | uint8_t result; 595 | 596 | __ASM volatile ("clz %0, %1" : "=r" (result) : "r" (value) ); 597 | return(result); 598 | } 599 | 600 | #endif /* (__CORTEX_M >= 0x03) */ 601 | 602 | 603 | 604 | 605 | #elif defined ( __TASKING__ ) /*------------------ TASKING Compiler --------------*/ 606 | /* TASKING carm specific functions */ 607 | 608 | /* 609 | * The CMSIS functions have been implemented as intrinsics in the compiler. 610 | * Please use "carm -?i" to get an up to date list of all intrinsics, 611 | * Including the CMSIS ones. 612 | */ 613 | 614 | #endif 615 | 616 | /*@}*/ /* end of group CMSIS_Core_InstructionInterface */ 617 | 618 | #endif /* __CORE_CMINSTR_H */ 619 | -------------------------------------------------------------------------------- /cmsis_boot/.readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /cmsis_boot/startup/.readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /cmsis_boot/startup/startup_stm32f10x_md_vl.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file startup_stm32f10x_md_vl.c 4 | * @author Coocox 5 | * @version V1.0 6 | * @date 3/4/2011 7 | * @brief STM32F10x Medium Density Value Line Devices Startup code. 8 | * This module performs: 9 | * - Set the initial SP 10 | * - Set the vector table entries with the exceptions ISR address 11 | * - Initialize data and bss 12 | * - Setup the microcontroller system. 13 | * - Call the application's entry point. 14 | * After Reset the Cortex-M3 processor is in Thread mode, 15 | * priority is Privileged, and the Stack is set to Main. 16 | ******************************************************************************* 17 | */ 18 | 19 | 20 | /*----------Stack Configuration-----------------------------------------------*/ 21 | #define STACK_SIZE 0x00000100 /*!< The Stack size suggest using even number */ 22 | __attribute__ ((section(".co_stack"))) 23 | unsigned long pulStack[STACK_SIZE]; 24 | 25 | 26 | /*----------Macro definition--------------------------------------------------*/ 27 | #define WEAK __attribute__ ((weak)) 28 | 29 | 30 | /*----------Declaration of the default fault handlers-------------------------*/ 31 | /* System exception vector handler */ 32 | __attribute__ ((used)) 33 | void WEAK Reset_Handler(void); 34 | void WEAK NMI_Handler(void); 35 | void WEAK HardFault_Handler(void); 36 | void WEAK MemManage_Handler(void); 37 | void WEAK BusFault_Handler(void); 38 | void WEAK UsageFault_Handler(void); 39 | void WEAK SVC_Handler(void); 40 | void WEAK DebugMon_Handler(void); 41 | void WEAK PendSV_Handler(void); 42 | void WEAK SysTick_Handler(void); 43 | void WEAK WWDG_IRQHandler(void); 44 | void WEAK PVD_IRQHandler(void); 45 | void WEAK TAMPER_IRQHandler(void); 46 | void WEAK RTC_IRQHandler(void); 47 | void WEAK FLASH_IRQHandler(void); 48 | void WEAK RCC_IRQHandler(void); 49 | void WEAK EXTI0_IRQHandler(void); 50 | void WEAK EXTI1_IRQHandler(void); 51 | void WEAK EXTI2_IRQHandler(void); 52 | void WEAK EXTI3_IRQHandler(void); 53 | void WEAK EXTI4_IRQHandler(void); 54 | void WEAK DMA1_Channel1_IRQHandler(void); 55 | void WEAK DMA1_Channel2_IRQHandler(void); 56 | void WEAK DMA1_Channel3_IRQHandler(void); 57 | void WEAK DMA1_Channel4_IRQHandler(void); 58 | void WEAK DMA1_Channel5_IRQHandler(void); 59 | void WEAK DMA1_Channel6_IRQHandler(void); 60 | void WEAK DMA1_Channel7_IRQHandler(void); 61 | void WEAK ADC1_IRQHandler(void); 62 | void WEAK EXTI9_5_IRQHandler(void); 63 | void WEAK TIM1_BRK_TIM15_IRQHandler(void); 64 | void WEAK TIM1_UP_TIM16_IRQHandler(void); 65 | void WEAK TIM1_TRG_COM_TIM17_IRQHandler(void); 66 | void WEAK TIM1_CC_IRQHandler(void); 67 | void WEAK TIM2_IRQHandler(void); 68 | void WEAK TIM3_IRQHandler(void); 69 | void WEAK TIM4_IRQHandler(void); 70 | void WEAK I2C1_EV_IRQHandler(void); 71 | void WEAK I2C1_ER_IRQHandler(void); 72 | void WEAK I2C2_EV_IRQHandler(void); 73 | void WEAK I2C2_ER_IRQHandler(void); 74 | void WEAK SPI1_IRQHandler(void); 75 | void WEAK SPI2_IRQHandler(void); 76 | void WEAK USART1_IRQHandler(void); 77 | void WEAK USART2_IRQHandler(void); 78 | void WEAK USART3_IRQHandler(void); 79 | void WEAK EXTI15_10_IRQHandler(void); 80 | void WEAK RTCAlarm_IRQHandler(void); 81 | void WEAK CEC_IRQHandler(void); 82 | void WEAK TIM6_DAC_IRQHandler(void); 83 | void WEAK TIM7_IRQHandler(void); 84 | 85 | /*----------Symbols defined in linker script----------------------------------*/ 86 | extern unsigned long _sidata; /*!< Start address for the initialization 87 | values of the .data section. */ 88 | extern unsigned long _sdata; /*!< Start address for the .data section */ 89 | extern unsigned long _edata; /*!< End address for the .data section */ 90 | extern unsigned long _sbss; /*!< Start address for the .bss section */ 91 | extern unsigned long _ebss; /*!< End address for the .bss section */ 92 | extern void _eram; /*!< End address for ram */ 93 | 94 | 95 | /*----------Function prototypes-----------------------------------------------*/ 96 | extern int main(void); /*!< The entry point for the application. */ 97 | extern void SystemInit(void); /*!< Setup the microcontroller system(CMSIS) */ 98 | void Default_Reset_Handler(void); /*!< Default reset handler */ 99 | static void Default_Handler(void); /*!< Default exception handler */ 100 | 101 | 102 | /** 103 | *@brief The minimal vector table for a Cortex M3. Note that the proper constructs 104 | * must be placed on this to ensure that it ends up at physical address 105 | * 0x00000000. 106 | */ 107 | __attribute__ ((used,section(".isr_vector"))) 108 | void (* const g_pfnVectors[])(void) = 109 | { 110 | /*----------Core Exceptions-------------------------------------------------*/ 111 | (void *)&pulStack[STACK_SIZE], /*!< The initial stack pointer */ 112 | Reset_Handler, /*!< Reset Handler */ 113 | NMI_Handler, /*!< NMI Handler */ 114 | HardFault_Handler, /*!< Hard Fault Handler */ 115 | MemManage_Handler, /*!< MPU Fault Handler */ 116 | BusFault_Handler, /*!< Bus Fault Handler */ 117 | UsageFault_Handler, /*!< Usage Fault Handler */ 118 | 0,0,0,0, /*!< Reserved */ 119 | SVC_Handler, /*!< SVCall Handler */ 120 | DebugMon_Handler, /*!< Debug Monitor Handler */ 121 | 0, /*!< Reserved */ 122 | PendSV_Handler, /*!< PendSV Handler */ 123 | SysTick_Handler, /*!< SysTick Handler */ 124 | 125 | /*----------External Exceptions---------------------------------------------*/ 126 | WWDG_IRQHandler, /*!< 0: Window Watchdog */ 127 | PVD_IRQHandler, /*!< 1: PVD through EXTI Line detect */ 128 | TAMPER_IRQHandler, /*!< 2: Tamper */ 129 | RTC_IRQHandler, /*!< 3: RTC */ 130 | FLASH_IRQHandler, /*!< 4: Flash */ 131 | RCC_IRQHandler, /*!< 5: RCC */ 132 | EXTI0_IRQHandler, /*!< 6: EXTI Line 0 */ 133 | EXTI1_IRQHandler, /*!< 7: EXTI Line 1 */ 134 | EXTI2_IRQHandler, /*!< 8: EXTI Line 2 */ 135 | EXTI3_IRQHandler, /*!< 9: EXTI Line 3 */ 136 | EXTI4_IRQHandler, /*!< 10: EXTI Line 4 */ 137 | DMA1_Channel1_IRQHandler, /*!< 11: DMA1 Channel 1 */ 138 | DMA1_Channel2_IRQHandler, /*!< 12: DMA1 Channel 2 */ 139 | DMA1_Channel3_IRQHandler, /*!< 13: DMA1 Channel 3 */ 140 | DMA1_Channel4_IRQHandler, /*!< 14: DMA1 Channel 4 */ 141 | DMA1_Channel5_IRQHandler, /*!< 15: DMA1 Channel 5 */ 142 | DMA1_Channel6_IRQHandler, /*!< 16: DMA1 Channel 6 */ 143 | DMA1_Channel7_IRQHandler, /*!< 17: DMA1 Channel 7 */ 144 | ADC1_IRQHandler, /*!< 18: ADC1 */ 145 | 0, /*!< 19: USB High Priority or CAN1 TX */ 146 | 0, /*!< 20: USB Low Priority or CAN1 RX0 */ 147 | 0, /*!< 21: CAN1 RX1 */ 148 | 0, /*!< 22: CAN1 SCE */ 149 | EXTI9_5_IRQHandler, /*!< 23: EXTI Line 9..5 */ 150 | TIM1_BRK_TIM15_IRQHandler, /*!< 24: TIM1 Break and TIM15 */ 151 | TIM1_UP_TIM16_IRQHandler, /*!< 25: TIM1 Update and TIM16 */ 152 | TIM1_TRG_COM_TIM17_IRQHandler,/*!< 26: TIM1 Trigger and Commutation and TIM17 */ 153 | TIM1_CC_IRQHandler, /*!< 27: TIM1 Capture Compare */ 154 | TIM2_IRQHandler, /*!< 28: TIM2 */ 155 | TIM3_IRQHandler, /*!< 29: TIM3 */ 156 | TIM4_IRQHandler, /*!< 30: TIM4 */ 157 | I2C1_EV_IRQHandler, /*!< 31: I2C1 Event */ 158 | I2C1_ER_IRQHandler, /*!< 32: I2C1 Error */ 159 | I2C2_EV_IRQHandler, /*!< 33: I2C2 Event */ 160 | I2C2_ER_IRQHandler, /*!< 34: I2C2 Error */ 161 | SPI1_IRQHandler, /*!< 35: SPI1 */ 162 | SPI2_IRQHandler, /*!< 36: SPI2 */ 163 | USART1_IRQHandler, /*!< 37: USART1 */ 164 | USART2_IRQHandler, /*!< 38: USART2 */ 165 | USART3_IRQHandler, /*!< 39: USART3 */ 166 | EXTI15_10_IRQHandler, /*!< 40: EXTI Line 15..10 */ 167 | RTCAlarm_IRQHandler, /*!< 41: RTC Alarm through EXTI Line */ 168 | CEC_IRQHandler, /*!< 42: HDMI-CEC */ 169 | 0,0,0,0,0,0, /*!< Reserved */ 170 | 0,0,0,0,0, /*!< Reserved */ 171 | TIM6_DAC_IRQHandler, /*!< 54: TIM6 and DAC underrun */ 172 | TIM7_IRQHandler, /*!< 55: TIM7 */ 173 | (void *)0xF108F85F /*!< Boot in RAM mode */ 174 | }; 175 | 176 | 177 | /** 178 | * @brief This is the code that gets called when the processor first 179 | * starts execution following a reset event. Only the absolutely 180 | * necessary set is performed, after which the application 181 | * supplied main() routine is called. 182 | * @param None 183 | * @retval None 184 | */ 185 | void Default_Reset_Handler(void) 186 | { 187 | /* Initialize data and bss */ 188 | unsigned long *pulSrc, *pulDest; 189 | 190 | /* Copy the data segment initializers from flash to SRAM */ 191 | pulSrc = &_sidata; 192 | 193 | for(pulDest = &_sdata; pulDest < &_edata; ) 194 | { 195 | *(pulDest++) = *(pulSrc++); 196 | } 197 | 198 | /* Zero fill the bss segment. This is done with inline assembly since this 199 | will clear the value of pulDest if it is not kept in a register. */ 200 | __asm(" ldr r0, =_sbss\n" 201 | " ldr r1, =_ebss\n" 202 | " mov r2, #0\n" 203 | " .thumb_func\n" 204 | " zero_loop:\n" 205 | " cmp r0, r1\n" 206 | " it lt\n" 207 | " strlt r2, [r0], #4\n" 208 | " blt zero_loop"); 209 | 210 | /* Setup the microcontroller system. */ 211 | //SystemInit(); 212 | 213 | /* Call the application's entry point.*/ 214 | main(); 215 | } 216 | 217 | /** 218 | *@brief Provide weak aliases for each Exception handler to the Default_Handler. 219 | * As they are weak aliases, any function with the same name will override 220 | * this definition. 221 | */ 222 | #pragma weak Reset_Handler = Default_Reset_Handler 223 | #pragma weak NMI_Handler = Default_Handler 224 | #pragma weak HardFault_Handler = Default_Handler 225 | #pragma weak MemManage_Handler = Default_Handler 226 | #pragma weak BusFault_Handler = Default_Handler 227 | #pragma weak UsageFault_Handler = Default_Handler 228 | #pragma weak SVC_Handler = Default_Handler 229 | #pragma weak DebugMon_Handler = Default_Handler 230 | #pragma weak PendSV_Handler = Default_Handler 231 | #pragma weak SysTick_Handler = Default_Handler 232 | #pragma weak WWDG_IRQHandler = Default_Handler 233 | #pragma weak PVD_IRQHandler = Default_Handler 234 | #pragma weak TAMPER_IRQHandler = Default_Handler 235 | #pragma weak RTC_IRQHandler = Default_Handler 236 | #pragma weak FLASH_IRQHandler = Default_Handler 237 | #pragma weak RCC_IRQHandler = Default_Handler 238 | #pragma weak EXTI0_IRQHandler = Default_Handler 239 | #pragma weak EXTI1_IRQHandler = Default_Handler 240 | #pragma weak EXTI2_IRQHandler = Default_Handler 241 | #pragma weak EXTI3_IRQHandler = Default_Handler 242 | #pragma weak EXTI4_IRQHandler = Default_Handler 243 | #pragma weak DMA1_Channel1_IRQHandler = Default_Handler 244 | #pragma weak DMA1_Channel2_IRQHandler = Default_Handler 245 | #pragma weak DMA1_Channel3_IRQHandler = Default_Handler 246 | #pragma weak DMA1_Channel4_IRQHandler = Default_Handler 247 | #pragma weak DMA1_Channel5_IRQHandler = Default_Handler 248 | #pragma weak DMA1_Channel6_IRQHandler = Default_Handler 249 | #pragma weak DMA1_Channel7_IRQHandler = Default_Handler 250 | #pragma weak ADC1_IRQHandler = Default_Handler 251 | #pragma weak EXTI9_5_IRQHandler = Default_Handler 252 | #pragma weak TIM1_BRK_TIM15_IRQHandler = Default_Handler 253 | #pragma weak TIM1_UP_TIM16_IRQHandler = Default_Handler 254 | #pragma weak TIM1_TRG_COM_TIM17_IRQHandler = Default_Handler 255 | #pragma weak TIM1_CC_IRQHandler = Default_Handler 256 | #pragma weak TIM2_IRQHandler = Default_Handler 257 | #pragma weak TIM3_IRQHandler = Default_Handler 258 | #pragma weak TIM4_IRQHandler = Default_Handler 259 | #pragma weak I2C1_EV_IRQHandler = Default_Handler 260 | #pragma weak I2C1_ER_IRQHandler = Default_Handler 261 | #pragma weak I2C2_EV_IRQHandler = Default_Handler 262 | #pragma weak I2C2_ER_IRQHandler = Default_Handler 263 | #pragma weak SPI1_IRQHandler = Default_Handler 264 | #pragma weak SPI2_IRQHandler = Default_Handler 265 | #pragma weak USART1_IRQHandler = Default_Handler 266 | #pragma weak USART2_IRQHandler = Default_Handler 267 | #pragma weak USART3_IRQHandler = Default_Handler 268 | #pragma weak EXTI15_10_IRQHandler = Default_Handler 269 | #pragma weak RTCAlarm_IRQHandler = Default_Handler 270 | #pragma weak CEC_IRQHandler = Default_Handler 271 | #pragma weak TIM6_DAC_IRQHandler = Default_Handler 272 | #pragma weak TIM7_IRQHandler = Default_Handler 273 | 274 | /** 275 | * @brief This is the code that gets called when the processor receives an 276 | * unexpected interrupt. This simply enters an infinite loop, 277 | * preserving the system state for examination by a debugger. 278 | * @param None 279 | * @retval None 280 | */ 281 | static void Default_Handler(void) 282 | { 283 | /* Go into an infinite loop. */ 284 | while (1) 285 | { 286 | } 287 | } 288 | 289 | /*********************** (C) COPYRIGHT 2011 Coocox ************END OF FILE*****/ 290 | -------------------------------------------------------------------------------- /cmsis_boot/stm32f10x.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darksidelemm/RS41FOX/9a4e4137032302171b62b3976e8ceb72193e5ecc/cmsis_boot/stm32f10x.h -------------------------------------------------------------------------------- /cmsis_boot/stm32f10x_conf.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file RTC/Calendar/stm32f10x_conf.h 4 | * @author MCD Application Team 5 | * @version V3.4.0 6 | * @date 10/15/2010 7 | * @brief Library configuration file. 8 | ****************************************************************************** 9 | * @copy 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 2010 STMicroelectronics

19 | */ 20 | 21 | /* Define to prevent recursive inclusion -------------------------------------*/ 22 | #ifndef __STM32F10x_CONF_H 23 | #define __STM32F10x_CONF_H 24 | 25 | /* Includes ------------------------------------------------------------------*/ 26 | /* Uncomment the line below to enable peripheral header file inclusion */ 27 | /* #include "stm32f10x_adc.h" */ 28 | /* #include "stm32f10x_bkp.h" */ 29 | /* #include "stm32f10x_can.h" */ 30 | /* #include "stm32f10x_cec.h" */ 31 | /* #include "stm32f10x_crc.h" */ 32 | /* #include "stm32f10x_dac.h" */ 33 | /* #include "stm32f10x_dbgmcu.h" */ 34 | /* #include "stm32f10x_dma.h" */ 35 | /* #include "stm32f10x_exti.h" */ 36 | /* #include "stm32f10x_flash.h" */ 37 | /* #include "stm32f10x_fsmc.h" */ 38 | /* #include "stm32f10x_gpio.h" */ 39 | /* #include "stm32f10x_i2c.h" */ 40 | /* #include "stm32f10x_iwdg.h" */ 41 | /* #include "stm32f10x_pwr.h" */ 42 | /* #include "stm32f10x_rcc.h" */ 43 | /* #include "stm32f10x_rtc.h" */ 44 | /* #include "stm32f10x_sdio.h" */ 45 | /* #include "stm32f10x_spi.h" */ 46 | /* #include "stm32f10x_tim.h" */ 47 | /* #include "stm32f10x_usart.h" */ 48 | /* #include "stm32f10x_wwdg.h" */ 49 | /* #include "misc.h" */ /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */ 50 | 51 | 52 | /* Exported types ------------------------------------------------------------*/ 53 | /* Exported constants --------------------------------------------------------*/ 54 | /* Uncomment the line below to expanse the "assert_param" macro in the 55 | Standard Peripheral Library drivers code */ 56 | /* #define USE_FULL_ASSERT 1 */ 57 | 58 | /* Exported macro ------------------------------------------------------------*/ 59 | #ifdef USE_FULL_ASSERT 60 | 61 | /** 62 | * @brief The assert_param macro is used for function's parameters check. 63 | * @param expr: If expr is false, it calls assert_failed function 64 | * which reports the name of the source file and the source 65 | * line number of the call that failed. 66 | * If expr is true, it returns no value. 67 | * @retval None 68 | */ 69 | #define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__)) 70 | /* Exported functions ------------------------------------------------------- */ 71 | void assert_failed(uint8_t* file, uint32_t line); 72 | #else 73 | #define assert_param(expr) ((void)0) 74 | #endif /* USE_FULL_ASSERT */ 75 | 76 | #endif /* __STM32F10x_CONF_H */ 77 | 78 | /******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/ 79 | -------------------------------------------------------------------------------- /cmsis_boot/system_stm32f10x.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file system_stm32f10x.h 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 11-March-2011 7 | * @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Header 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 | /** @addtogroup CMSIS 23 | * @{ 24 | */ 25 | 26 | /** @addtogroup stm32f10x_system 27 | * @{ 28 | */ 29 | 30 | /** 31 | * @brief Define to prevent recursive inclusion 32 | */ 33 | #ifndef __SYSTEM_STM32F10X_H 34 | #define __SYSTEM_STM32F10X_H 35 | 36 | #ifdef __cplusplus 37 | extern "C" { 38 | #endif 39 | 40 | /** @addtogroup STM32F10x_System_Includes 41 | * @{ 42 | */ 43 | 44 | /** 45 | * @} 46 | */ 47 | 48 | 49 | /** @addtogroup STM32F10x_System_Exported_types 50 | * @{ 51 | */ 52 | 53 | extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */ 54 | 55 | /** 56 | * @} 57 | */ 58 | 59 | /** @addtogroup STM32F10x_System_Exported_Constants 60 | * @{ 61 | */ 62 | 63 | /** 64 | * @} 65 | */ 66 | 67 | /** @addtogroup STM32F10x_System_Exported_Macros 68 | * @{ 69 | */ 70 | 71 | /** 72 | * @} 73 | */ 74 | 75 | /** @addtogroup STM32F10x_System_Exported_Functions 76 | * @{ 77 | */ 78 | 79 | extern void SystemInit(void); 80 | extern void SystemCoreClockUpdate(void); 81 | /** 82 | * @} 83 | */ 84 | 85 | #ifdef __cplusplus 86 | } 87 | #endif 88 | 89 | #endif /*__SYSTEM_STM32F10X_H */ 90 | 91 | /** 92 | * @} 93 | */ 94 | 95 | /** 96 | * @} 97 | */ 98 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 99 | -------------------------------------------------------------------------------- /config.h: -------------------------------------------------------------------------------- 1 | // RS41FOX Config File. 2 | 3 | #ifndef RS41HUP_CONFIG_H 4 | #define RS41HUP_CONFIG_H 5 | 6 | #ifdef USE_EXTERNAL_CONFIG 7 | #include "config_external.h" 8 | #else 9 | 10 | 11 | //************GLOBAL Settings***************** 12 | #define TRANSMIT_FREQUENCY 434.650f // MHz. (Default is within the ISM band. ARDF Frequency in Australia is 439.4 MHz) 13 | #define CALLSIGN "N0CALL" // Put your callsign here, max. 15 characters 14 | 15 | #define MODULATE_FM // Enable CW via FM tone generation (leave commented for CW) 16 | #define FM_TONE_FREQ 1000 // FM CW modulation frequency (in Hz) 17 | #define FM_TX_DELAY 500 // TX delay in ms 18 | 19 | // TX Power 20 | #define TX_POWER 5 // PWR 0...7 0- MIN ... 7 - MAX 21 | // Power Levels measured at 434.650 MHz, using a Rigol DSA815, and a 10 kHz RBW 22 | // Power measured by connecting a short (30cm) length of RG316 directly to the 23 | // antenna/ground pads at the bottom of the RS41 PCB. 24 | // 0 --> -1.9dBm 25 | // 1 --> 1.3dBm 26 | // 2 --> 3.6dBm 27 | // 3 --> 7.0dBm 28 | // 4 --> 10.0dBm 29 | // 5 --> 13.1dBm - DEFAULT 30 | // 6 --> 15.0dBm 31 | // 7 --> 16.3dBm 32 | 33 | 34 | //*************BEACON SETTINGS**************** 35 | // Morse Ident speed. 36 | #define MORSE_WPM 20 37 | 38 | // CW beacon on & off times. 39 | #define ON_TIME 10 // Seconds 40 | #define OFF_TIME 10 // Seconds 41 | 42 | // Number of On/Off Repeats. 43 | #define ONOFF_REPEATS 1 44 | 45 | // Low-Voltage Beacon 46 | // If enabled (uncommmented), beacon the lat/lon of the fox in the CW ident when the battery voltage gets low. 47 | // NOTE: If you are going to place the fox in a location with no GPS reception, disable this mode, 48 | // else it will draw lots of power trying to acquire GPS signal. 49 | #define LOW_VOLTAGE_BEACON 1 50 | 51 | // Low-Voltage beacon threshold voltage. For ~4-5 hours of position beaconing before going flat, use: 52 | // Lithium AA: 2.7 volts (Refer 100mA discharge curve here: http://data.energizer.com/pdfs/l91.pdf ) 53 | // Alkaline AA: 2.2 volts (Refer 100mA discharge curve here: http://data.energizer.com/pdfs/e91.pdf ) 54 | #define LOW_VOLTAGE_BEACON_THRESHOLD 2.2 // Volts 55 | 56 | // Low-Voltage Cutout - Kill power if the supply drops below this level. Useful to avoid destroying cells. 57 | // Set this to < 1 Volt for (essentially) no low-voltage cutout. 58 | #define LOW_VOLTAGE_CUTOUT 0.5 // Volts 59 | 60 | // Power Button Debounce Time in ms - Set this to 0 to disable the power button. Set this to the desired turn-off 61 | // time in milliseconds (typically 500) to enable the power button. The power button must be held for this time to 62 | // turn off the fox. 63 | #define POWER_BUTTON_DEBOUNCE_TIME 500 64 | 65 | #endif 66 | #endif //RS41HUP_CONFIG_H -------------------------------------------------------------------------------- /delay.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "delay.h" 7 | 8 | volatile uint8_t done; 9 | 10 | void delay_init() { 11 | TIM_TimeBaseInitTypeDef ts; 12 | // TIM3 @ APB1 -> 6MHz WTF?! 13 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); 14 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE); 15 | 16 | ts.TIM_Prescaler = 6 - 1; 17 | ts.TIM_CounterMode = TIM_CounterMode_Up; 18 | ts.TIM_Period = 0; 19 | ts.TIM_ClockDivision = TIM_CKD_DIV1; 20 | ts.TIM_RepetitionCounter = 0; 21 | 22 | TIM_TimeBaseInit(TIM3,&ts); 23 | TIM_ClearITPendingBit(TIM3, TIM_IT_Update); 24 | TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE); 25 | NVIC_InitTypeDef NVIC_InitStructure; //create NVIC structure 26 | NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; 27 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 28 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 29 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 30 | NVIC_Init(&NVIC_InitStructure); 31 | TIM_Cmd(TIM3, DISABLE); 32 | } 33 | 34 | void _delay_us(uint16_t us, uint8_t precise) { 35 | TIM_Cmd(TIM3, DISABLE); 36 | TIM_SetAutoreload(TIM3, us); 37 | TIM_SetCounter(TIM3, 0); 38 | TIM_Cmd(TIM3, ENABLE); 39 | done = 0; 40 | while(!done){ 41 | 42 | } 43 | TIM_Cmd(TIM3, DISABLE); 44 | } 45 | 46 | inline void _delay_ms(uint32_t ms) { 47 | while(ms-- > 0){ 48 | _delay_us(1000, 0); 49 | } 50 | } 51 | 52 | void TIM3_IRQHandler(void) { 53 | if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { 54 | TIM_ClearITPendingBit(TIM3, TIM_IT_Update); 55 | done = 1; 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /delay.h: -------------------------------------------------------------------------------- 1 | #ifndef __DELAY_H_ 2 | #define __DELAY_H_ 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | /** Initialize delay core - configure SysTick timer */ 8 | void delay_init(); 9 | 10 | void _delay_us(uint16_t us, uint8_t precise); 11 | 12 | void _delay_ms(uint32_t ms); 13 | 14 | #ifdef __cplusplus 15 | } 16 | #endif 17 | #endif 18 | -------------------------------------------------------------------------------- /docs/programming_header.md: -------------------------------------------------------------------------------- 1 | # Vaisala RS41 Expansion Connector Pinout 2 | Based on work by DF8OE 3 | 4 | 5 | Viewed into port from outside 6 | ``` 7 | ----------| |---------- 8 | | 9 7 5 3 1 | 9 | | | 10 | | 10 8 6 4 2 | 11 | --------------------------- 12 | ``` 13 | 14 | Suitable Plug: Molex 87568-1073 (element14 order code 1365756) 15 | 16 | * 1 - GND 17 | * 2 - I2C_SDA (PB11) 18 | * 3 - I2C_SCL (PB10) 19 | * 4 - +VDD_MCU 20 | * 5 - MCU Switched 3.3V out to external device 21 | * 6 - +V_Battery 22 | * 7 - RST 23 | * 8 - SWCLK (PA14) 24 | * 9 - SWDIO (PA13) 25 | * 10 - GND 26 | 27 | 28 | -------------------------------------------------------------------------------- /flash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Basic Black Magic Probe GDB automation script, from https://github.com/blacksphere/blackmagic/wiki/GDB-Automation 3 | # 4 | # Change the /dev/cu. path below to your SWD debugger. 5 | # 6 | # Also assumes arm-none-eabi-gdb is in your $PATH 7 | 8 | arm-none-eabi-gdb -nx --batch \ 9 | -ex 'target extended-remote /dev/cu.usbmodem7BAD9DB1' \ 10 | -ex 'monitor swdp_scan' \ 11 | -ex 'attach 1' \ 12 | -ex 'load' \ 13 | -ex 'compare-sections' \ 14 | -ex 'kill' \ 15 | RS41HUP.elf -------------------------------------------------------------------------------- /init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include "init.h" 12 | #include "radio.h" 13 | 14 | __IO uint16_t ADCVal[2]; 15 | 16 | SPI_InitTypeDef SPI_InitStructure; 17 | USART_InitTypeDef USART_InitStructure; 18 | GPIO_InitTypeDef GPIO_Conf; 19 | ADC_InitTypeDef ADC_InitStructure; 20 | DMA_InitTypeDef DMA_InitStructure; 21 | 22 | 23 | #define ADC1_DR_Address ((uint32_t)0x4001244C) 24 | #if defined(STM32F10X_CL) 25 | #error "clock oscillator problem!" 26 | #endif 27 | void init_usart_gps(const uint32_t speed, const uint8_t enable_irq) { 28 | NVIC_DisableIRQ(USART1_IRQn); 29 | USART_ITConfig(USART1, USART_IT_RXNE, DISABLE); 30 | USART_ClearITPendingBit(USART1, USART_IT_RXNE); 31 | USART_ClearITPendingBit(USART1, USART_IT_ORE); 32 | 33 | USART_Cmd(USART1, DISABLE); 34 | 35 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); 36 | USART_InitStructure.USART_BaudRate = speed; 37 | USART_InitStructure.USART_WordLength = USART_WordLength_8b; 38 | USART_InitStructure.USART_StopBits = USART_StopBits_1; 39 | USART_InitStructure.USART_Parity = USART_Parity_No; 40 | USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 41 | USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; 42 | USART_Init(USART1, &USART_InitStructure); 43 | 44 | NVIC_InitTypeDef NVIC_InitStructure; //create NVIC structure 45 | NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; 46 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15; 47 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; 48 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 49 | NVIC_Init(&NVIC_InitStructure); 50 | 51 | USART_Cmd(USART1, ENABLE); 52 | if (enable_irq){ 53 | USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); 54 | NVIC_EnableIRQ(USART1_IRQn); 55 | } 56 | } 57 | 58 | void init_usart_debug() { 59 | NVIC_DisableIRQ(USART3_IRQn); 60 | USART_Cmd(USART3, DISABLE); 61 | 62 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE); 63 | USART_InitStructure.USART_BaudRate = 19200; //0x9c4; 64 | USART_InitStructure.USART_WordLength = USART_WordLength_8b; 65 | USART_InitStructure.USART_StopBits = USART_StopBits_1; 66 | USART_InitStructure.USART_Parity = USART_Parity_No; 67 | USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; 68 | USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; 69 | USART_Init(USART3, &USART_InitStructure); 70 | USART_Cmd(USART3, ENABLE); 71 | } 72 | 73 | void NVIC_Conf() 74 | { 75 | #ifdef VECT_TAB_RAM 76 | NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 77 | #else // VECT_TAB_FLASH 78 | NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); 79 | #endif 80 | } 81 | 82 | void RCC_Conf() 83 | { 84 | ErrorStatus HSEStartUpStatus; 85 | RCC_DeInit(); 86 | RCC_HSEConfig(RCC_HSE_ON); 87 | HSEStartUpStatus = RCC_WaitForHSEStartUp(); 88 | if(HSEStartUpStatus == SUCCESS) 89 | { 90 | FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable); 91 | FLASH_SetLatency(FLASH_Latency_2); 92 | RCC_HCLKConfig(RCC_SYSCLK_Div4); 93 | RCC_PCLK2Config(RCC_HCLK_Div4); 94 | RCC_PCLK1Config(RCC_HCLK_Div2); 95 | RCC_SYSCLKConfig(RCC_SYSCLKSource_HSE); 96 | while(RCC_GetSYSCLKSource() != 0x04); 97 | } 98 | } 99 | 100 | void init_port() 101 | { 102 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 103 | GPIO_Conf.GPIO_Pin = GPIO_Pin_12; 104 | GPIO_Conf.GPIO_Mode = GPIO_Mode_Out_PP; 105 | GPIO_Conf.GPIO_Speed = GPIO_Speed_10MHz; 106 | GPIO_Init(GPIOA, &GPIO_Conf); 107 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 108 | GPIO_Conf.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8; 109 | GPIO_Conf.GPIO_Mode = GPIO_Mode_Out_PP; 110 | GPIO_Conf.GPIO_Speed = GPIO_Speed_10MHz; 111 | GPIO_Init(GPIOB, &GPIO_Conf); 112 | 113 | // SPI2_SCK & SPI2_MOSI 114 | GPIO_Conf.GPIO_Pin = GPIO_Pin_13 | radioSDIpin; 115 | GPIO_Conf.GPIO_Mode = GPIO_Mode_AF_PP; 116 | GPIO_Conf.GPIO_Speed = GPIO_Speed_10MHz; 117 | GPIO_Init(GPIOB, &GPIO_Conf); 118 | 119 | // SPI2_MISO 120 | GPIO_Conf.GPIO_Pin = GPIO_Pin_14; 121 | GPIO_Conf.GPIO_Mode = GPIO_Mode_IN_FLOATING; 122 | GPIO_Init(GPIOB, &GPIO_Conf); 123 | 124 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); 125 | 126 | // radioNSELpin 127 | GPIO_Conf.GPIO_Pin = radioNSELpin; 128 | GPIO_Conf.GPIO_Mode = GPIO_Mode_Out_PP; 129 | GPIO_Conf.GPIO_Speed = GPIO_Speed_10MHz; 130 | GPIO_Init(GPIOC,&GPIO_Conf); 131 | 132 | spi_init(); 133 | 134 | GPIO_Conf.GPIO_Pin = GPIO_Pin_9; 135 | GPIO_Conf.GPIO_Mode = GPIO_Mode_AF_PP; 136 | GPIO_Conf.GPIO_Speed = GPIO_Speed_10MHz; 137 | GPIO_Init(GPIOA, &GPIO_Conf); 138 | GPIO_Conf.GPIO_Pin = GPIO_Pin_10; 139 | GPIO_Conf.GPIO_Mode = GPIO_Mode_IN_FLOATING; 140 | GPIO_Init(GPIOA, &GPIO_Conf); 141 | 142 | init_usart_gps(9600, 0); 143 | 144 | GPIO_Conf.GPIO_Pin = GPIO_Pin_10; 145 | GPIO_Conf.GPIO_Mode = GPIO_Mode_AF_PP; 146 | GPIO_Conf.GPIO_Speed = GPIO_Speed_10MHz; 147 | GPIO_Init(GPIOB, &GPIO_Conf); 148 | GPIO_Conf.GPIO_Pin = GPIO_Pin_11; 149 | GPIO_Conf.GPIO_Mode = GPIO_Mode_IN_FLOATING; 150 | GPIO_Init(GPIOB, &GPIO_Conf); 151 | 152 | init_usart_debug(); 153 | 154 | RCC_AHBPeriphClockCmd ( RCC_AHBPeriph_DMA1 , ENABLE ) ; 155 | DMA_DeInit(DMA1_Channel1); 156 | DMA_InitStructure.DMA_BufferSize = 2; 157 | DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; 158 | DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; 159 | DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t) &ADCVal; 160 | ADC_DMACmd(ADC1, ENABLE); 161 | DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; 162 | DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; 163 | DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; 164 | DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; 165 | DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; 166 | DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 167 | DMA_InitStructure.DMA_Priority = DMA_Priority_High; 168 | DMA_Init(DMA1_Channel1, &DMA_InitStructure); 169 | DMA_Cmd(DMA1_Channel1, ENABLE); 170 | GPIO_Conf.GPIO_Mode = GPIO_Mode_AIN; 171 | GPIO_Conf.GPIO_Pin = GPIO_Pin_6 ; // that's ADC1 (PA5 on STM32) 172 | GPIO_Init(GPIOA, &GPIO_Conf); 173 | GPIO_Conf.GPIO_Mode = GPIO_Mode_AIN; 174 | GPIO_Conf.GPIO_Pin = GPIO_Pin_5 ; // that's ADC1 (PA3 on STM32) 175 | GPIO_Init(GPIOA, &GPIO_Conf); 176 | RCC_ADCCLKConfig (RCC_PCLK2_Div2); 177 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 178 | ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; 179 | ADC_InitStructure.ADC_ScanConvMode = ENABLE; 180 | ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; // we work in continuous sampling mode 181 | ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; 182 | ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 183 | ADC_InitStructure.ADC_NbrOfChannel = 2; 184 | ADC_Init ( ADC1, &ADC_InitStructure); //set config of ADC1 185 | ADC_RegularChannelConfig(ADC1,ADC_Channel_5, 1,ADC_SampleTime_28Cycles5); // define regular conversion config 186 | ADC_RegularChannelConfig(ADC1,ADC_Channel_6, 2,ADC_SampleTime_28Cycles5); // define regular conversion config 187 | ADC_DMACmd(ADC1, ENABLE); 188 | ADC_Cmd (ADC1,ENABLE); //enable ADC 189 | ADC_ResetCalibration(ADC1); // Reset previous calibration 190 | while(ADC_GetResetCalibrationStatus(ADC1)); 191 | ADC_StartCalibration(ADC1); // start new calibration (ADC must be off at that time) 192 | while(ADC_GetCalibrationStatus(ADC1)); 193 | ADC_SoftwareStartConvCmd(ADC1, ENABLE); // start conversion (will be endless as we are in continuous mode) 194 | } 195 | 196 | void spi_init() { 197 | GPIO_Conf.GPIO_Pin = radioSDIpin; 198 | GPIO_Conf.GPIO_Mode = GPIO_Mode_AF_PP; 199 | GPIO_Conf.GPIO_Speed = GPIO_Speed_10MHz; 200 | GPIO_Init(GPIOB, &GPIO_Conf); 201 | 202 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE); 203 | SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; 204 | SPI_InitStructure.SPI_Mode = SPI_Mode_Master; 205 | SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b; 206 | SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; 207 | SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; 208 | SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16; 209 | SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; 210 | SPI_InitStructure.SPI_CRCPolynomial = 7; 211 | SPI_Init(SPI2, &SPI_InitStructure); 212 | SPI_SSOutputCmd(SPI2, ENABLE); 213 | SPI_Cmd(SPI2, ENABLE); 214 | SPI_InitStructure.SPI_Mode = SPI_Mode_Master; 215 | SPI_Init(SPI2, &SPI_InitStructure); 216 | } 217 | 218 | void spi_deinit() { 219 | SPI_I2S_DeInit(SPI2); 220 | GPIO_Conf.GPIO_Pin = radioSDIpin; 221 | GPIO_Conf.GPIO_Mode = GPIO_Mode_Out_PP; 222 | GPIO_Conf.GPIO_Speed = GPIO_Speed_10MHz; 223 | GPIO_Init(GPIOB, &GPIO_Conf); 224 | 225 | } 226 | 227 | void init_timer(const int rtty_speed) { 228 | TIM_TimeBaseInitTypeDef TIM2_TimeBaseInitStruct; 229 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 230 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, DISABLE); 231 | 232 | TIM2_TimeBaseInitStruct.TIM_Prescaler = 6 - 1; // tick every 1/1000000 s 233 | TIM2_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up; 234 | TIM2_TimeBaseInitStruct.TIM_Period = (uint16_t) ((1000000 / rtty_speed) - 1); 235 | TIM2_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1; 236 | TIM2_TimeBaseInitStruct.TIM_RepetitionCounter = 0; 237 | 238 | TIM_TimeBaseInit(TIM2,&TIM2_TimeBaseInitStruct); 239 | TIM_ClearITPendingBit(TIM2, TIM_IT_Update); 240 | TIM_ITConfig(TIM2,TIM_IT_Update, ENABLE); 241 | NVIC_InitTypeDef NVIC_InitStructure; //create NVIC structure 242 | NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; 243 | NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; 244 | NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; 245 | NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 246 | NVIC_Init(&NVIC_InitStructure); 247 | TIM_Cmd(TIM2,ENABLE); 248 | } -------------------------------------------------------------------------------- /init.h: -------------------------------------------------------------------------------- 1 | extern __IO uint16_t ADCVal[2]; 2 | #ifdef __cplusplus 3 | extern "C" { 4 | #endif 5 | 6 | void NVIC_Conf(); 7 | 8 | void RCC_Conf(); 9 | 10 | void init_port(); 11 | 12 | void init_timer(const int rtty_speed); 13 | 14 | void init_usart_gps(const uint32_t speed, const uint8_t enable_irq); 15 | 16 | void spi_init(); 17 | 18 | void spi_deinit(); 19 | #ifdef __cplusplus 20 | } 21 | #endif 22 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | // STM32F100 and SI4032 RTTY transmitter 2 | // released under GPL v.2 by anonymous developer 3 | // enjoy and have a nice day 4 | // ver 1.5a 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "stdlib.h" 13 | #include 14 | #include 15 | #include 16 | #include "init.h" 17 | #include "config.h" 18 | #include "radio.h" 19 | #include "ublox.h" 20 | #include "delay.h" 21 | #include "util.h" 22 | #include "morse.h" 23 | 24 | // IO Pin Definitions. The state of these pins are initilised in init.c 25 | #define GREEN GPIO_Pin_7 // Inverted 26 | #define RED GPIO_Pin_8 // Non-Inverted (?) 27 | #define SHUTDOWN GPIO_Pin_12 // Set high to trigger the power circuitry to power down. 28 | 29 | 30 | // Telemetry Data to Transmit 31 | int voltage; 32 | GPSEntry gpsData; 33 | int gpsFixed = 0; 34 | // String and Transmit Buffers 35 | char callsign[15] = {CALLSIGN}; 36 | char buf_tx[200]; 37 | 38 | 39 | // Function Definitions 40 | void collect_telemetry_data(); 41 | void send_rtty_message(); 42 | void send_morse_ident(); 43 | void send_low_battery_beacon(); 44 | void power_down(); 45 | void check_supply_voltage(); 46 | void check_gps_lock(); 47 | void check_power_button(); 48 | 49 | /** 50 | * GPS data processing 51 | */ 52 | void USART1_IRQHandler(void) { 53 | if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { 54 | ublox_handle_incoming_byte((uint8_t) USART_ReceiveData(USART1)); 55 | }else if (USART_GetITStatus(USART1, USART_IT_ORE) != RESET) { 56 | USART_ReceiveData(USART1); 57 | } else { 58 | USART_ReceiveData(USART1); 59 | } 60 | } 61 | 62 | 63 | int main(void) { 64 | RCC_Conf(); 65 | NVIC_Conf(); 66 | init_port(); 67 | 68 | delay_init(); 69 | ublox_init(); 70 | 71 | GPIO_SetBits(GPIOB, RED); 72 | // NOTE - Green LED is inverted. (Reset to activate, Set to deactivate) 73 | GPIO_SetBits(GPIOB, GREEN); 74 | USART_SendData(USART3, 0xc); 75 | 76 | radio_soft_reset(); 77 | // Set Morse TX Frequency 78 | radio_set_tx_frequency(TRANSMIT_FREQUENCY); 79 | 80 | // Set PLL offset to 0 81 | radio_rw_register(0x73, 0x00, 1); 82 | 83 | // setting TX power 84 | radio_rw_register(0x6D, 00 | (TX_POWER & 0x0007), 1); 85 | 86 | // initial RTTY modulation 87 | radio_rw_register(0x71, 0x00, 1); 88 | 89 | // Temperature Value Offset 90 | radio_rw_register(0x13, 0xF0, 1); 91 | 92 | // Temperature Sensor Calibration 93 | radio_rw_register(0x12, 0x00, 1); 94 | 95 | // ADC configuration 96 | radio_rw_register(0x0f, 0x80, 1); 97 | 98 | // For some reason we have to do this again... 99 | spi_init(); 100 | radio_set_tx_frequency(TRANSMIT_FREQUENCY); 101 | radio_rw_register(0x71, 0x00, 1); 102 | 103 | // If we aren't doing a low-voltage GPS position beacon, 104 | // just disable the GPS from the start. 105 | #ifndef LOW_VOLTAGE_BEACON 106 | ublox_gps_stop(); 107 | #endif 108 | 109 | // Main Transmission Loop. 110 | while (1) { 111 | // Loop. 112 | send_morse_ident(); 113 | _delay_ms(1000); 114 | 115 | for(int k = 0; k < ONOFF_REPEATS; k++){ 116 | radio_enable_tx(); 117 | radio_enable_tone(); 118 | for(int i = 0; i < ON_TIME; i++){ 119 | check_power_button(); 120 | _delay_ms(1000); 121 | } 122 | radio_inhibit_tone(); 123 | radio_disable_tx(); 124 | 125 | for(int i = 0; i < OFF_TIME; i++){ 126 | check_power_button(); 127 | _delay_ms(1000); 128 | } 129 | } 130 | 131 | #ifdef LOW_VOLTAGE_BEACON 132 | check_gps_lock(); 133 | #endif 134 | check_supply_voltage(); 135 | check_power_button(); 136 | } 137 | } 138 | 139 | // Possible power savings? 140 | //NVIC_SystemLPConfig(NVIC_LP_SEVONPEND, DISABLE); 141 | //__WFI(); 142 | 143 | 144 | void send_morse_ident(){ 145 | // Grab battery voltage data 146 | voltage = ADCVal[0] * 600 / 4096; 147 | int _voltage_v = voltage/100; 148 | int _voltage_mv = voltage % 100; 149 | 150 | sprintf(buf_tx, "DE %s FOX %d.%02dV", callsign, _voltage_v, _voltage_mv); 151 | sendMorse(buf_tx); 152 | } 153 | 154 | 155 | void send_low_battery_beacon(){ 156 | // Send an alternating tone beacon, to indicate the battery is getting low. 157 | radio_enable_tx(); 158 | for(int i = 0; i<10; i++){ 159 | radio_rw_register(0x73, 0x02, 1); 160 | _delay_ms(200); 161 | radio_rw_register(0x73, 0x00, 1); 162 | _delay_ms(200); 163 | } 164 | radio_disable_tx(); 165 | _delay_ms(1000); 166 | } 167 | 168 | void power_down(){ 169 | // Pulsing GPIO 12 de-latches the power supply circuitry, 170 | // killing power to the board. 171 | GPIO_SetBits(GPIOA, SHUTDOWN); 172 | } 173 | 174 | void check_supply_voltage(){ 175 | voltage = ADCVal[0] * 600 / 4096; 176 | 177 | #ifdef LOW_VOLTAGE_BEACON 178 | if( (float)(voltage)/100.0 < LOW_VOLTAGE_BEACON_THRESHOLD){ 179 | // Send a beacon signal to indicate we are in low-battery mode. 180 | send_low_battery_beacon(); 181 | 182 | // Send the calculated GPS position if we have GPS lock. 183 | if(gpsData.fix < 3){ 184 | sendMorse("NO GPS LOCK "); 185 | } 186 | else { 187 | // Convert raw lat/lon values into degrees and decimal degree values. 188 | uint8_t lat_d = (uint8_t) abs(gpsData.lat_raw / 10000000); 189 | uint32_t lat_fl = (uint32_t) abs(abs(gpsData.lat_raw) - lat_d * 10000000) / 1000; 190 | uint8_t lon_d = (uint8_t) abs(gpsData.lon_raw / 10000000); 191 | uint32_t lon_fl = (uint32_t) abs(abs(gpsData.lon_raw) - lon_d * 10000000) / 1000; 192 | 193 | sprintf(buf_tx, "%s FOX %s%d.%04ld %s%d.%04ld ", 194 | callsign, 195 | gpsData.lat_raw < 0 ? "S" : "N", lat_d, lat_fl, 196 | gpsData.lon_raw < 0 ? "W" : "E", lon_d, lon_fl 197 | ); 198 | sendMorse(buf_tx); 199 | } 200 | } 201 | #endif 202 | 203 | if( (float)(voltage)/100 < LOW_VOLTAGE_CUTOUT){ 204 | sendMorse("LOW BATTERY "); 205 | power_down(); 206 | } 207 | } 208 | 209 | void check_gps_lock(){ 210 | // If we have lock, return immediately. 211 | if(gpsFixed){ 212 | return; 213 | } 214 | 215 | // Otherwise, check to see if we have lock. 216 | else { 217 | ublox_get_last_data(&gpsData); 218 | } 219 | 220 | if(gpsData.fix >= 3){ 221 | // We have GPS lock! 222 | sendMorse("GPS LOCK "); 223 | gpsFixed = 1; 224 | 225 | // Disable the GPS unit. This saves ~200mW of power. 226 | ublox_gps_stop(); 227 | } 228 | 229 | } 230 | 231 | void check_power_button(){ 232 | #if POWER_BUTTON_DEBOUNCE_TIME 233 | 234 | const static uint16_t button_pressed_threshold = 2000; 235 | 236 | // Increase a counter for each cycle that the power button is pressed. 237 | // When count exceeds the equivalent debounce time, power down. 238 | uint16_t count = 0; 239 | do { 240 | count++; 241 | _delay_ms(25); 242 | 243 | if(count > (POWER_BUTTON_DEBOUNCE_TIME / 25)) { 244 | // The user-initiated power off sequence needs to have an acknowledgement and delay so they release the power button. 245 | // Continuing to press the power button after shutdown is asserted will turn the RS41 on again. 246 | 247 | // Disable transmit and enable the green LED (in an "ACK" sort of way) 248 | radio_disable_tx(); 249 | GPIO_ResetBits(GPIOB, GREEN); 250 | _delay_ms(500); 251 | GPIO_SetBits(GPIOB, GREEN); 252 | 253 | // Flash the red LED and transmit 3 times 254 | for(int i = 0; i < 3; i++) { 255 | radio_enable_tx(); 256 | GPIO_ResetBits(GPIOB, RED); 257 | _delay_ms(750); 258 | radio_disable_tx(); 259 | GPIO_SetBits(GPIOB, RED); 260 | _delay_ms(250); 261 | } 262 | power_down(); 263 | } 264 | } while (ADCVal[1] > button_pressed_threshold); 265 | 266 | #endif 267 | } -------------------------------------------------------------------------------- /morse.c: -------------------------------------------------------------------------------- 1 | // 2 | // Morse Code Playback Functions 3 | // Mark Jessop 2018-04 4 | // 5 | // Based on code from https://github.com/Paradoxis/Arduino-morse-code-translator/blob/master/main.ino 6 | // 7 | #include "morse.h" 8 | 9 | // Letters 10 | char* MORSE_LETTERS[] = { 11 | ".-", // A 12 | "-...", // B 13 | "-.-.", // C 14 | "-..", // D 15 | ".", // E 16 | "..-.", // F 17 | "--.", // G 18 | "....", // H 19 | "..", // I 20 | ".---", // J 21 | "-.-", // K 22 | ".-..", // L 23 | "--", // M 24 | "-.", // N 25 | "---", // O 26 | ".--.", // P 27 | "--.-", // Q 28 | ".-.", // R 29 | "...", // S 30 | "-", // T 31 | "..-", // U 32 | "...-", // V 33 | ".--", // W 34 | "-..-", // X 35 | "-.--", // Y 36 | "--.." // Z 37 | }; 38 | 39 | 40 | 41 | // Numerals. 42 | char* MORSE_NUMBERS[] = { 43 | "-----", // 0 44 | ".----", // 1 45 | "..---", // 2 46 | "...--", // 3 47 | "....-", // 4 48 | ".....", // 5 49 | "-....", // 6 50 | "--...", // 7 51 | "---..", // 8 52 | "----." // 9 53 | }; 54 | 55 | // Symbols (though we handle this in a bit of a hacky way.) 56 | char* MORSE_SYMBOLS[] = { 57 | ".-.-.-", // . 58 | "-..-." // / 59 | }; 60 | 61 | 62 | // Send a single character 63 | void sendDotOrDash (char unit) { 64 | 65 | radio_enable_tone(); 66 | 67 | // Unit is a dot (500 ms) 68 | if (unit == MORSE_DOT) { 69 | _delay_ms(MORSE_DELAY_DOT); 70 | } 71 | 72 | // Unit is a dash (1500 ms) 73 | if (unit == MORSE_DASH) { 74 | _delay_ms(MORSE_DELAY_DASH); 75 | } 76 | 77 | // Inter-element gap 78 | radio_inhibit_tone(); 79 | _delay_ms(MORSE_DELAY); 80 | } 81 | 82 | 83 | void sendMorseSequence (char* sequence) { 84 | 85 | // Counter 86 | int i = 0; 87 | 88 | // Loop through every character until an 'end-of-line' (null) character is found 89 | while (sequence[i] != '\0') { 90 | sendDotOrDash(sequence[i]); 91 | i++; 92 | } 93 | 94 | // Delay between every letter 95 | _delay_ms(MORSE_DELAY * 3); 96 | } 97 | 98 | 99 | 100 | void sendMorse(char* message) { 101 | 102 | radio_enable_tx(); 103 | 104 | int i = 0; 105 | while (message[i] != '\0') { 106 | char current = message[i]; 107 | 108 | // Lower case letters 109 | if (current >= 'a' && current <= 'z') { 110 | sendMorseSequence(MORSE_LETTERS[current - 'a']); 111 | } 112 | 113 | // Capital case letters 114 | else if (current >= 'A' && current <= 'Z') { 115 | sendMorseSequence(MORSE_LETTERS[current - 'A']); 116 | } 117 | 118 | // Numbers 119 | else if (current >= '0' && current <= '9') { 120 | sendMorseSequence(MORSE_NUMBERS[current - '0']); 121 | } 122 | 123 | else if (current == '.') { 124 | sendMorseSequence(MORSE_SYMBOLS[0]); 125 | } 126 | 127 | else if (current == '/') { 128 | sendMorseSequence(MORSE_SYMBOLS[1]); 129 | } 130 | 131 | // Space character (3500 ms) 132 | else if (current == ' ') { 133 | _delay_ms(MORSE_DELAY_SPACE); 134 | } 135 | 136 | // Treat all other characters as a space. 137 | else { 138 | _delay_ms(MORSE_DELAY_SPACE); 139 | } 140 | 141 | i++; 142 | } 143 | 144 | radio_disable_tx(); 145 | } 146 | 147 | 148 | -------------------------------------------------------------------------------- /morse.h: -------------------------------------------------------------------------------- 1 | // 2 | // Morse Code Playback Functions 3 | // Mark Jessop 2018-04 4 | // 5 | #ifndef RS41FOX_MORSE_H 6 | #define RS41FOX_MORSE_H 7 | 8 | #include "config.h" 9 | #include "radio.h" 10 | #include "delay.h" 11 | 12 | // All morse delays 13 | #define MORSE_DELAY 1200 / MORSE_WPM 14 | #define MORSE_DELAY_DOT (MORSE_DELAY * 1) 15 | #define MORSE_DELAY_DASH (MORSE_DELAY * 3) 16 | #define MORSE_DELAY_SPACE (MORSE_DELAY * 7) 17 | 18 | // All morse characters 19 | #define MORSE_DOT '.' 20 | #define MORSE_DASH '-' 21 | 22 | void sendDotOrDash (char unit); 23 | void sendMorseSequence (char* sequence); 24 | void sendMorse(char* message); 25 | 26 | 27 | #endif //RS41FOX_MORSE_H 28 | -------------------------------------------------------------------------------- /pwm.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "pwm.h" 10 | #include "config.h" 11 | #include "radio.h" 12 | 13 | DMA_Channel_TypeDef *pwm_dma_channel = DMA1_Channel2; 14 | 15 | void pwm_timer_init() 16 | { 17 | TIM_DeInit(TIM15); 18 | // GPIO_PinRemapConfig(GPIO_Remap_TIM15, DISABLE); 19 | 20 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, ENABLE); 21 | RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM15, DISABLE); 22 | 23 | TIM_TimeBaseInitTypeDef tim_init; 24 | 25 | // Not needed: TIM_InternalClockConfig(TIM15); 26 | 27 | tim_init.TIM_Prescaler = 6 - 1; // tick every 1 us 28 | tim_init.TIM_CounterMode = TIM_CounterMode_Up; 29 | tim_init.TIM_Period = (uint16_t) (1000000 / (FM_TONE_FREQ * 4)) - 1; 30 | tim_init.TIM_ClockDivision = TIM_CKD_DIV1; 31 | tim_init.TIM_RepetitionCounter = 0; 32 | 33 | TIM_TimeBaseInit(TIM15, &tim_init); 34 | 35 | // TIM_OCInitTypeDef TIM15_OCInitStruct; 36 | 37 | // TIM_OCStructInit(&TIM15_OCInitStruct); 38 | // TIM15_OCInitStruct.TIM_Pulse = 0; // Was: tim_init.TIM_Period / 2 39 | // TIM15_OCInitStruct.TIM_OCMode = TIM_OCMode_Toggle; // Was: TIM_OCMode_PWM1 40 | // TIM15_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable; 41 | // TIM15_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High; 42 | 43 | // // TIM15 channel 2 can be used to drive pin PB15, which is connected to RS41 Si4032 SDI pin for direct modulation 44 | // TIM_OC2Init(TIM15, &TIM15_OCInitStruct); 45 | 46 | // // These are not needed? 47 | // // TIM_SelectOCxM(TIM15, TIM_Channel_2, TIM_OCMode_PWM1); 48 | // // TIM_CCxCmd(TIM15, TIM_Channel_2, TIM_CCx_Enable); 49 | 50 | // // The following settings make transitions between generated frequencies smooth 51 | // TIM_ARRPreloadConfig(TIM15, ENABLE); 52 | // TIM_OC2PreloadConfig(TIM15, TIM_OCPreload_Enable); 53 | 54 | // TIM_OC2FastConfig(TIM15, TIM_OCFast_Enable); 55 | 56 | // TIM_CtrlPWMOutputs(TIM15, DISABLE); 57 | 58 | TIM_ClearITPendingBit(TIM15, TIM_IT_Update); 59 | TIM_ITConfig(TIM15, TIM_IT_Update, ENABLE); 60 | 61 | NVIC_InitTypeDef nvic_init; 62 | nvic_init.NVIC_IRQChannel = TIM1_BRK_TIM15_IRQn; 63 | nvic_init.NVIC_IRQChannelPreemptionPriority = 2; 64 | nvic_init.NVIC_IRQChannelSubPriority = 1; 65 | nvic_init.NVIC_IRQChannelCmd = ENABLE; 66 | NVIC_Init(&nvic_init); 67 | 68 | TIM_Cmd(TIM15, ENABLE); 69 | } 70 | 71 | void pwm_timer_pwm_enable(bool enabled) 72 | { 73 | TIM_Cmd(TIM15, enabled ? ENABLE : DISABLE); 74 | // TIM_CtrlPWMOutputs(TIM15, enabled ? ENABLE : DISABLE); 75 | } 76 | 77 | void pwm_timer_use(bool use) 78 | { 79 | // Remapping the TIM15 outputs will allow TIM15 channel 2 can be used to drive pin PB15, 80 | // which is connected to RS41 Si4032 SDI pin for direct modulation 81 | // GPIO_PinRemapConfig(GPIO_Remap_TIM15, use ? ENABLE : DISABLE); 82 | } 83 | 84 | void pwm_timer_uninit() 85 | { 86 | TIM_CtrlPWMOutputs(TIM15, DISABLE); 87 | TIM_Cmd(TIM15, DISABLE); 88 | 89 | TIM_DeInit(TIM15); 90 | 91 | // GPIO_PinRemapConfig(GPIO_Remap_TIM15, DISABLE); 92 | 93 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM15, DISABLE); 94 | } 95 | 96 | inline uint16_t pwm_calculate_period(uint32_t frequency_hz) 97 | { 98 | return (uint16_t) (1000000 / frequency_hz) - 1; 99 | } 100 | 101 | inline void pwm_timer_set_frequency(uint32_t pwm_period) 102 | { 103 | TIM_SetAutoreload(TIM15, pwm_period); 104 | } 105 | 106 | void TIM1_BRK_TIM15_IRQHandler(void) 107 | { 108 | static bool pin_state = false; 109 | 110 | if (TIM_GetITStatus(TIM15, TIM_IT_Update) != RESET) { 111 | TIM_ClearITPendingBit(TIM15, TIM_IT_Update); 112 | // Restrict the interrupt to DFM17 only just in case this ISR gets called on RS41 113 | pin_state = !pin_state; 114 | GPIO_WriteBit(GPIOB, radioSDIpin, pin_state); 115 | } 116 | } -------------------------------------------------------------------------------- /pwm.h: -------------------------------------------------------------------------------- 1 | #ifndef __PWM_H_ 2 | #define __PWM_H_ 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include "pwm.h" 15 | #include "config.h" 16 | 17 | void pwm_timer_init(); 18 | 19 | void pwm_timer_pwm_enable(bool enabled); 20 | 21 | void pwm_timer_use(bool use); 22 | 23 | void pwm_timer_uninit(); 24 | 25 | uint16_t pwm_calculate_period(uint32_t frequency_hz); 26 | 27 | void pwm_timer_set_frequency(uint32_t pwm_period); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | #endif 33 | -------------------------------------------------------------------------------- /radio.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SQ5RWU on 2016-12-24. 3 | // 4 | 5 | #include "radio.h" 6 | 7 | uint8_t _spi_sendrecv(const uint16_t data_word) { 8 | GPIO_ResetBits(GPIOC, radioNSELpin); 9 | // wait for tx buffer 10 | while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET); 11 | SPI_I2S_SendData(SPI2, data_word); 12 | 13 | // wait for data in rx buffer 14 | while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET); 15 | GPIO_SetBits(GPIOC, radioNSELpin); 16 | return (uint8_t) SPI_I2S_ReceiveData(SPI2); 17 | } 18 | 19 | inline uint8_t radio_rw_register(const uint8_t register_addr, uint8_t value, uint8_t write){ 20 | return _spi_sendrecv(((write ? register_addr | WR : register_addr) << 8) | value); 21 | } 22 | 23 | void radio_set_tx_frequency(const float freq_in_mhz) { 24 | uint8_t hbsel = (uint8_t) ((freq_in_mhz * (30.0f / SI4032_CLOCK)) >= 480.0f ? 1 : 0); 25 | 26 | uint8_t fb = (uint8_t) ((((uint8_t)((freq_in_mhz * (30.0f / SI4032_CLOCK)) / 10) - 24) - (24 * hbsel)) / (1 + hbsel)); 27 | uint8_t gen_div = 3; // constant - not possible to change! 28 | uint16_t fc = (uint16_t) (((freq_in_mhz / ((SI4032_CLOCK / gen_div) * (hbsel + 1))) - fb - 24) * 64000); 29 | radio_rw_register(0x75, (uint8_t) (0b01000000 | (fb & 0b11111) | ((hbsel & 0b1) << 5)), 1); 30 | radio_rw_register(0x76, (uint8_t) (((uint16_t)fc >> 8) & 0xff), 1); 31 | radio_rw_register(0x77, (uint8_t) ((uint16_t)fc & 0xff), 1); 32 | } 33 | 34 | void radio_enable_tx() { 35 | #ifdef MODULATE_FM 36 | // Set modulation to FSK, direct async mode 37 | radio_rw_register(0x71, 0b00010010, 1); 38 | 39 | // Set deviation to 3.125KHz (625Hz * 5) 40 | radio_rw_register(0x72, 5, 1); 41 | 42 | // Enable TX 43 | radio_rw_register(0x07, 0x4B, 1); 44 | 45 | // Deinitialize SPI bus (shared pin with radio data in) 46 | spi_deinit(); 47 | 48 | _delay_ms(FM_TX_DELAY); 49 | 50 | // Initialize PWM timer 51 | pwm_timer_init(); 52 | pwm_timer_use(true); 53 | 54 | GPIO_SetBits(GPIOC, radioNSELpin); 55 | 56 | #endif 57 | } 58 | 59 | void radio_disable_tx() { 60 | #ifdef MODULATE_FM 61 | pwm_timer_uninit(); 62 | 63 | GPIO_ResetBits(GPIOC, radioNSELpin); 64 | 65 | spi_init(); 66 | #endif 67 | 68 | radio_rw_register(0x07, 0x40, 1); 69 | } 70 | 71 | void radio_soft_reset() { 72 | radio_rw_register(0x07, 0x80, 1); 73 | } 74 | 75 | void radio_enable_tone() { 76 | #ifndef MODULATE_FM 77 | // Modified to set the PLL and Crystal enable bits to high. Not sure if this makes much differents. 78 | radio_rw_register(0x07, 0x4B, 1); 79 | #else 80 | pwm_timer_pwm_enable(true); 81 | #endif 82 | } 83 | 84 | void radio_inhibit_tone() { 85 | #ifndef MODULATE_FM 86 | // Sleep mode, but with PLL idle mode enabled, in an attempt to reduce drift on key-up. 87 | radio_rw_register(0x07, 0x43, 1); 88 | #else 89 | pwm_timer_pwm_enable(false); 90 | #endif 91 | } 92 | 93 | int8_t radio_read_temperature() { 94 | uint8_t temp; 95 | temp = radio_rw_register(0x11, 0xff, 0); // read ADC 96 | int8_t temperatura = (int8_t) (-64 + (temp * 5 / 10) - 16); 97 | radio_rw_register(0x0f, 0x80, 1); 98 | return temperatura; 99 | } -------------------------------------------------------------------------------- /radio.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SQ5RWU on 2016-12-24. 3 | // 4 | 5 | #ifndef RS41HUP_RADIO_H 6 | #define RS41HUP_RADIO_H 7 | 8 | #include "config.h" 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "pwm.h" 14 | #include "init.h" 15 | #include "delay.h" 16 | 17 | static const uint16_t radioNSELpin = GPIO_Pin_13; // @ GPIOC 18 | static const uint16_t radioSDIpin = GPIO_Pin_15; // @ GPIOB! 19 | static const uint8_t WR = 0x80; 20 | static const float SI4032_CLOCK = 26.0; 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | uint8_t _spi_sendrecv(const uint16_t data_word); 27 | 28 | uint8_t radio_rw_register(const uint8_t register_addr, uint8_t value, uint8_t write); 29 | 30 | void radio_set_tx_frequency(const float radio_set_tx_frequency); 31 | 32 | void radio_enable_tx(); 33 | 34 | void radio_disable_tx(); 35 | 36 | void radio_soft_reset(); 37 | 38 | void radio_enable_tone(); 39 | 40 | void radio_inhibit_tone(); 41 | 42 | int8_t radio_read_temperature(); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | 48 | #endif //RS41HUP_RADIO_H 49 | -------------------------------------------------------------------------------- /stm_lib/.readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /stm_lib/inc/.readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /stm_lib/inc/misc.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file misc.h 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 11-March-2011 7 | * @brief This file contains all the functions prototypes for the miscellaneous 8 | * firmware library functions (add-on to CMSIS functions). 9 | ****************************************************************************** 10 | * @attention 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 | *

© COPYRIGHT 2011 STMicroelectronics

20 | ****************************************************************************** 21 | */ 22 | 23 | /* Define to prevent recursive inclusion -------------------------------------*/ 24 | #ifndef __MISC_H 25 | #define __MISC_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /* Includes ------------------------------------------------------------------*/ 32 | #include "stm32f10x.h" 33 | 34 | /** @addtogroup STM32F10x_StdPeriph_Driver 35 | * @{ 36 | */ 37 | 38 | /** @addtogroup MISC 39 | * @{ 40 | */ 41 | 42 | /** @defgroup MISC_Exported_Types 43 | * @{ 44 | */ 45 | 46 | /** 47 | * @brief NVIC Init Structure definition 48 | */ 49 | 50 | typedef struct 51 | { 52 | uint8_t NVIC_IRQChannel; /*!< Specifies the IRQ channel to be enabled or disabled. 53 | This parameter can be a value of @ref IRQn_Type 54 | (For the complete STM32 Devices IRQ Channels list, please 55 | refer to stm32f10x.h file) */ 56 | 57 | uint8_t NVIC_IRQChannelPreemptionPriority; /*!< Specifies the pre-emption priority for the IRQ channel 58 | specified in NVIC_IRQChannel. This parameter can be a value 59 | between 0 and 15 as described in the table @ref NVIC_Priority_Table */ 60 | 61 | uint8_t NVIC_IRQChannelSubPriority; /*!< Specifies the subpriority level for the IRQ channel specified 62 | in NVIC_IRQChannel. This parameter can be a value 63 | between 0 and 15 as described in the table @ref NVIC_Priority_Table */ 64 | 65 | FunctionalState NVIC_IRQChannelCmd; /*!< Specifies whether the IRQ channel defined in NVIC_IRQChannel 66 | will be enabled or disabled. 67 | This parameter can be set either to ENABLE or DISABLE */ 68 | } NVIC_InitTypeDef; 69 | 70 | /** 71 | * @} 72 | */ 73 | 74 | /** @defgroup NVIC_Priority_Table 75 | * @{ 76 | */ 77 | 78 | /** 79 | @code 80 | The table below gives the allowed values of the pre-emption priority and subpriority according 81 | to the Priority Grouping configuration performed by NVIC_PriorityGroupConfig function 82 | ============================================================================================================================ 83 | NVIC_PriorityGroup | NVIC_IRQChannelPreemptionPriority | NVIC_IRQChannelSubPriority | Description 84 | ============================================================================================================================ 85 | NVIC_PriorityGroup_0 | 0 | 0-15 | 0 bits for pre-emption priority 86 | | | | 4 bits for subpriority 87 | ---------------------------------------------------------------------------------------------------------------------------- 88 | NVIC_PriorityGroup_1 | 0-1 | 0-7 | 1 bits for pre-emption priority 89 | | | | 3 bits for subpriority 90 | ---------------------------------------------------------------------------------------------------------------------------- 91 | NVIC_PriorityGroup_2 | 0-3 | 0-3 | 2 bits for pre-emption priority 92 | | | | 2 bits for subpriority 93 | ---------------------------------------------------------------------------------------------------------------------------- 94 | NVIC_PriorityGroup_3 | 0-7 | 0-1 | 3 bits for pre-emption priority 95 | | | | 1 bits for subpriority 96 | ---------------------------------------------------------------------------------------------------------------------------- 97 | NVIC_PriorityGroup_4 | 0-15 | 0 | 4 bits for pre-emption priority 98 | | | | 0 bits for subpriority 99 | ============================================================================================================================ 100 | @endcode 101 | */ 102 | 103 | /** 104 | * @} 105 | */ 106 | 107 | /** @defgroup MISC_Exported_Constants 108 | * @{ 109 | */ 110 | 111 | /** @defgroup Vector_Table_Base 112 | * @{ 113 | */ 114 | 115 | #define NVIC_VectTab_RAM ((uint32_t)0x20000000) 116 | #define NVIC_VectTab_FLASH ((uint32_t)0x08000000) 117 | #define IS_NVIC_VECTTAB(VECTTAB) (((VECTTAB) == NVIC_VectTab_RAM) || \ 118 | ((VECTTAB) == NVIC_VectTab_FLASH)) 119 | /** 120 | * @} 121 | */ 122 | 123 | /** @defgroup System_Low_Power 124 | * @{ 125 | */ 126 | 127 | #define NVIC_LP_SEVONPEND ((uint8_t)0x10) 128 | #define NVIC_LP_SLEEPDEEP ((uint8_t)0x04) 129 | #define NVIC_LP_SLEEPONEXIT ((uint8_t)0x02) 130 | #define IS_NVIC_LP(LP) (((LP) == NVIC_LP_SEVONPEND) || \ 131 | ((LP) == NVIC_LP_SLEEPDEEP) || \ 132 | ((LP) == NVIC_LP_SLEEPONEXIT)) 133 | /** 134 | * @} 135 | */ 136 | 137 | /** @defgroup Preemption_Priority_Group 138 | * @{ 139 | */ 140 | 141 | #define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority 142 | 4 bits for subpriority */ 143 | #define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority 144 | 3 bits for subpriority */ 145 | #define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority 146 | 2 bits for subpriority */ 147 | #define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority 148 | 1 bits for subpriority */ 149 | #define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority 150 | 0 bits for subpriority */ 151 | 152 | #define IS_NVIC_PRIORITY_GROUP(GROUP) (((GROUP) == NVIC_PriorityGroup_0) || \ 153 | ((GROUP) == NVIC_PriorityGroup_1) || \ 154 | ((GROUP) == NVIC_PriorityGroup_2) || \ 155 | ((GROUP) == NVIC_PriorityGroup_3) || \ 156 | ((GROUP) == NVIC_PriorityGroup_4)) 157 | 158 | #define IS_NVIC_PREEMPTION_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) 159 | 160 | #define IS_NVIC_SUB_PRIORITY(PRIORITY) ((PRIORITY) < 0x10) 161 | 162 | #define IS_NVIC_OFFSET(OFFSET) ((OFFSET) < 0x000FFFFF) 163 | 164 | /** 165 | * @} 166 | */ 167 | 168 | /** @defgroup SysTick_clock_source 169 | * @{ 170 | */ 171 | 172 | #define SysTick_CLKSource_HCLK_Div8 ((uint32_t)0xFFFFFFFB) 173 | #define SysTick_CLKSource_HCLK ((uint32_t)0x00000004) 174 | #define IS_SYSTICK_CLK_SOURCE(SOURCE) (((SOURCE) == SysTick_CLKSource_HCLK) || \ 175 | ((SOURCE) == SysTick_CLKSource_HCLK_Div8)) 176 | /** 177 | * @} 178 | */ 179 | 180 | /** 181 | * @} 182 | */ 183 | 184 | /** @defgroup MISC_Exported_Macros 185 | * @{ 186 | */ 187 | 188 | /** 189 | * @} 190 | */ 191 | 192 | /** @defgroup MISC_Exported_Functions 193 | * @{ 194 | */ 195 | 196 | void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup); 197 | void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct); 198 | void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset); 199 | void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState); 200 | void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource); 201 | 202 | #ifdef __cplusplus 203 | } 204 | #endif 205 | 206 | #endif /* __MISC_H */ 207 | 208 | /** 209 | * @} 210 | */ 211 | 212 | /** 213 | * @} 214 | */ 215 | 216 | /** 217 | * @} 218 | */ 219 | 220 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 221 | -------------------------------------------------------------------------------- /stm_lib/inc/stm32f10x_pwr.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f10x_pwr.h 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 11-March-2011 7 | * @brief This file contains all the functions prototypes for the PWR firmware 8 | * library. 9 | ****************************************************************************** 10 | * @attention 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 | *

© COPYRIGHT 2011 STMicroelectronics

20 | ****************************************************************************** 21 | */ 22 | 23 | /* Define to prevent recursive inclusion -------------------------------------*/ 24 | #ifndef __STM32F10x_PWR_H 25 | #define __STM32F10x_PWR_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /* Includes ------------------------------------------------------------------*/ 32 | #include "stm32f10x.h" 33 | 34 | /** @addtogroup STM32F10x_StdPeriph_Driver 35 | * @{ 36 | */ 37 | 38 | /** @addtogroup PWR 39 | * @{ 40 | */ 41 | 42 | /** @defgroup PWR_Exported_Types 43 | * @{ 44 | */ 45 | 46 | /** 47 | * @} 48 | */ 49 | 50 | /** @defgroup PWR_Exported_Constants 51 | * @{ 52 | */ 53 | 54 | /** @defgroup PVD_detection_level 55 | * @{ 56 | */ 57 | 58 | #define PWR_PVDLevel_2V2 ((uint32_t)0x00000000) 59 | #define PWR_PVDLevel_2V3 ((uint32_t)0x00000020) 60 | #define PWR_PVDLevel_2V4 ((uint32_t)0x00000040) 61 | #define PWR_PVDLevel_2V5 ((uint32_t)0x00000060) 62 | #define PWR_PVDLevel_2V6 ((uint32_t)0x00000080) 63 | #define PWR_PVDLevel_2V7 ((uint32_t)0x000000A0) 64 | #define PWR_PVDLevel_2V8 ((uint32_t)0x000000C0) 65 | #define PWR_PVDLevel_2V9 ((uint32_t)0x000000E0) 66 | #define IS_PWR_PVD_LEVEL(LEVEL) (((LEVEL) == PWR_PVDLevel_2V2) || ((LEVEL) == PWR_PVDLevel_2V3)|| \ 67 | ((LEVEL) == PWR_PVDLevel_2V4) || ((LEVEL) == PWR_PVDLevel_2V5)|| \ 68 | ((LEVEL) == PWR_PVDLevel_2V6) || ((LEVEL) == PWR_PVDLevel_2V7)|| \ 69 | ((LEVEL) == PWR_PVDLevel_2V8) || ((LEVEL) == PWR_PVDLevel_2V9)) 70 | /** 71 | * @} 72 | */ 73 | 74 | /** @defgroup Regulator_state_is_STOP_mode 75 | * @{ 76 | */ 77 | 78 | #define PWR_Regulator_ON ((uint32_t)0x00000000) 79 | #define PWR_Regulator_LowPower ((uint32_t)0x00000001) 80 | #define IS_PWR_REGULATOR(REGULATOR) (((REGULATOR) == PWR_Regulator_ON) || \ 81 | ((REGULATOR) == PWR_Regulator_LowPower)) 82 | /** 83 | * @} 84 | */ 85 | 86 | /** @defgroup STOP_mode_entry 87 | * @{ 88 | */ 89 | 90 | #define PWR_STOPEntry_WFI ((uint8_t)0x01) 91 | #define PWR_STOPEntry_WFE ((uint8_t)0x02) 92 | #define IS_PWR_STOP_ENTRY(ENTRY) (((ENTRY) == PWR_STOPEntry_WFI) || ((ENTRY) == PWR_STOPEntry_WFE)) 93 | 94 | /** 95 | * @} 96 | */ 97 | 98 | /** @defgroup PWR_Flag 99 | * @{ 100 | */ 101 | 102 | #define PWR_FLAG_WU ((uint32_t)0x00000001) 103 | #define PWR_FLAG_SB ((uint32_t)0x00000002) 104 | #define PWR_FLAG_PVDO ((uint32_t)0x00000004) 105 | #define IS_PWR_GET_FLAG(FLAG) (((FLAG) == PWR_FLAG_WU) || ((FLAG) == PWR_FLAG_SB) || \ 106 | ((FLAG) == PWR_FLAG_PVDO)) 107 | 108 | #define IS_PWR_CLEAR_FLAG(FLAG) (((FLAG) == PWR_FLAG_WU) || ((FLAG) == PWR_FLAG_SB)) 109 | /** 110 | * @} 111 | */ 112 | 113 | /** 114 | * @} 115 | */ 116 | 117 | /** @defgroup PWR_Exported_Macros 118 | * @{ 119 | */ 120 | 121 | /** 122 | * @} 123 | */ 124 | 125 | /** @defgroup PWR_Exported_Functions 126 | * @{ 127 | */ 128 | 129 | void PWR_DeInit(void); 130 | void PWR_BackupAccessCmd(FunctionalState NewState); 131 | void PWR_PVDCmd(FunctionalState NewState); 132 | void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel); 133 | void PWR_WakeUpPinCmd(FunctionalState NewState); 134 | void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry); 135 | void PWR_EnterSTANDBYMode(void); 136 | FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG); 137 | void PWR_ClearFlag(uint32_t PWR_FLAG); 138 | 139 | #ifdef __cplusplus 140 | } 141 | #endif 142 | 143 | #endif /* __STM32F10x_PWR_H */ 144 | /** 145 | * @} 146 | */ 147 | 148 | /** 149 | * @} 150 | */ 151 | 152 | /** 153 | * @} 154 | */ 155 | 156 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 157 | -------------------------------------------------------------------------------- /stm_lib/inc/stm32f10x_spi.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f10x_spi.h 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 11-March-2011 7 | * @brief This file contains all the functions prototypes for the SPI firmware 8 | * library. 9 | ****************************************************************************** 10 | * @attention 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 | *

© COPYRIGHT 2011 STMicroelectronics

20 | ****************************************************************************** 21 | */ 22 | 23 | /* Define to prevent recursive inclusion -------------------------------------*/ 24 | #ifndef __STM32F10x_SPI_H 25 | #define __STM32F10x_SPI_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /* Includes ------------------------------------------------------------------*/ 32 | #include "stm32f10x.h" 33 | 34 | /** @addtogroup STM32F10x_StdPeriph_Driver 35 | * @{ 36 | */ 37 | 38 | /** @addtogroup SPI 39 | * @{ 40 | */ 41 | 42 | /** @defgroup SPI_Exported_Types 43 | * @{ 44 | */ 45 | 46 | /** 47 | * @brief SPI Init structure definition 48 | */ 49 | 50 | typedef struct 51 | { 52 | uint16_t SPI_Direction; /*!< Specifies the SPI unidirectional or bidirectional data mode. 53 | This parameter can be a value of @ref SPI_data_direction */ 54 | 55 | uint16_t SPI_Mode; /*!< Specifies the SPI operating mode. 56 | This parameter can be a value of @ref SPI_mode */ 57 | 58 | uint16_t SPI_DataSize; /*!< Specifies the SPI data size. 59 | This parameter can be a value of @ref SPI_data_size */ 60 | 61 | uint16_t SPI_CPOL; /*!< Specifies the serial clock steady state. 62 | This parameter can be a value of @ref SPI_Clock_Polarity */ 63 | 64 | uint16_t SPI_CPHA; /*!< Specifies the clock active edge for the bit capture. 65 | This parameter can be a value of @ref SPI_Clock_Phase */ 66 | 67 | uint16_t SPI_NSS; /*!< Specifies whether the NSS signal is managed by 68 | hardware (NSS pin) or by software using the SSI bit. 69 | This parameter can be a value of @ref SPI_Slave_Select_management */ 70 | 71 | uint16_t SPI_BaudRatePrescaler; /*!< Specifies the Baud Rate prescaler value which will be 72 | used to configure the transmit and receive SCK clock. 73 | This parameter can be a value of @ref SPI_BaudRate_Prescaler. 74 | @note The communication clock is derived from the master 75 | clock. The slave clock does not need to be set. */ 76 | 77 | uint16_t SPI_FirstBit; /*!< Specifies whether data transfers start from MSB or LSB bit. 78 | This parameter can be a value of @ref SPI_MSB_LSB_transmission */ 79 | 80 | uint16_t SPI_CRCPolynomial; /*!< Specifies the polynomial used for the CRC calculation. */ 81 | }SPI_InitTypeDef; 82 | 83 | /** 84 | * @brief I2S Init structure definition 85 | */ 86 | 87 | typedef struct 88 | { 89 | 90 | uint16_t I2S_Mode; /*!< Specifies the I2S operating mode. 91 | This parameter can be a value of @ref I2S_Mode */ 92 | 93 | uint16_t I2S_Standard; /*!< Specifies the standard used for the I2S communication. 94 | This parameter can be a value of @ref I2S_Standard */ 95 | 96 | uint16_t I2S_DataFormat; /*!< Specifies the data format for the I2S communication. 97 | This parameter can be a value of @ref I2S_Data_Format */ 98 | 99 | uint16_t I2S_MCLKOutput; /*!< Specifies whether the I2S MCLK output is enabled or not. 100 | This parameter can be a value of @ref I2S_MCLK_Output */ 101 | 102 | uint32_t I2S_AudioFreq; /*!< Specifies the frequency selected for the I2S communication. 103 | This parameter can be a value of @ref I2S_Audio_Frequency */ 104 | 105 | uint16_t I2S_CPOL; /*!< Specifies the idle state of the I2S clock. 106 | This parameter can be a value of @ref I2S_Clock_Polarity */ 107 | }I2S_InitTypeDef; 108 | 109 | /** 110 | * @} 111 | */ 112 | 113 | /** @defgroup SPI_Exported_Constants 114 | * @{ 115 | */ 116 | 117 | #define IS_SPI_ALL_PERIPH(PERIPH) (((PERIPH) == SPI1) || \ 118 | ((PERIPH) == SPI2) || \ 119 | ((PERIPH) == SPI3)) 120 | 121 | #define IS_SPI_23_PERIPH(PERIPH) (((PERIPH) == SPI2) || \ 122 | ((PERIPH) == SPI3)) 123 | 124 | /** @defgroup SPI_data_direction 125 | * @{ 126 | */ 127 | 128 | #define SPI_Direction_2Lines_FullDuplex ((uint16_t)0x0000) 129 | #define SPI_Direction_2Lines_RxOnly ((uint16_t)0x0400) 130 | #define SPI_Direction_1Line_Rx ((uint16_t)0x8000) 131 | #define SPI_Direction_1Line_Tx ((uint16_t)0xC000) 132 | #define IS_SPI_DIRECTION_MODE(MODE) (((MODE) == SPI_Direction_2Lines_FullDuplex) || \ 133 | ((MODE) == SPI_Direction_2Lines_RxOnly) || \ 134 | ((MODE) == SPI_Direction_1Line_Rx) || \ 135 | ((MODE) == SPI_Direction_1Line_Tx)) 136 | /** 137 | * @} 138 | */ 139 | 140 | /** @defgroup SPI_mode 141 | * @{ 142 | */ 143 | 144 | #define SPI_Mode_Master ((uint16_t)0x0104) 145 | #define SPI_Mode_Slave ((uint16_t)0x0000) 146 | #define IS_SPI_MODE(MODE) (((MODE) == SPI_Mode_Master) || \ 147 | ((MODE) == SPI_Mode_Slave)) 148 | /** 149 | * @} 150 | */ 151 | 152 | /** @defgroup SPI_data_size 153 | * @{ 154 | */ 155 | 156 | #define SPI_DataSize_16b ((uint16_t)0x0800) 157 | #define SPI_DataSize_8b ((uint16_t)0x0000) 158 | #define IS_SPI_DATASIZE(DATASIZE) (((DATASIZE) == SPI_DataSize_16b) || \ 159 | ((DATASIZE) == SPI_DataSize_8b)) 160 | /** 161 | * @} 162 | */ 163 | 164 | /** @defgroup SPI_Clock_Polarity 165 | * @{ 166 | */ 167 | 168 | #define SPI_CPOL_Low ((uint16_t)0x0000) 169 | #define SPI_CPOL_High ((uint16_t)0x0002) 170 | #define IS_SPI_CPOL(CPOL) (((CPOL) == SPI_CPOL_Low) || \ 171 | ((CPOL) == SPI_CPOL_High)) 172 | /** 173 | * @} 174 | */ 175 | 176 | /** @defgroup SPI_Clock_Phase 177 | * @{ 178 | */ 179 | 180 | #define SPI_CPHA_1Edge ((uint16_t)0x0000) 181 | #define SPI_CPHA_2Edge ((uint16_t)0x0001) 182 | #define IS_SPI_CPHA(CPHA) (((CPHA) == SPI_CPHA_1Edge) || \ 183 | ((CPHA) == SPI_CPHA_2Edge)) 184 | /** 185 | * @} 186 | */ 187 | 188 | /** @defgroup SPI_Slave_Select_management 189 | * @{ 190 | */ 191 | 192 | #define SPI_NSS_Soft ((uint16_t)0x0200) 193 | #define SPI_NSS_Hard ((uint16_t)0x0000) 194 | #define IS_SPI_NSS(NSS) (((NSS) == SPI_NSS_Soft) || \ 195 | ((NSS) == SPI_NSS_Hard)) 196 | /** 197 | * @} 198 | */ 199 | 200 | /** @defgroup SPI_BaudRate_Prescaler 201 | * @{ 202 | */ 203 | 204 | #define SPI_BaudRatePrescaler_2 ((uint16_t)0x0000) 205 | #define SPI_BaudRatePrescaler_4 ((uint16_t)0x0008) 206 | #define SPI_BaudRatePrescaler_8 ((uint16_t)0x0010) 207 | #define SPI_BaudRatePrescaler_16 ((uint16_t)0x0018) 208 | #define SPI_BaudRatePrescaler_32 ((uint16_t)0x0020) 209 | #define SPI_BaudRatePrescaler_64 ((uint16_t)0x0028) 210 | #define SPI_BaudRatePrescaler_128 ((uint16_t)0x0030) 211 | #define SPI_BaudRatePrescaler_256 ((uint16_t)0x0038) 212 | #define IS_SPI_BAUDRATE_PRESCALER(PRESCALER) (((PRESCALER) == SPI_BaudRatePrescaler_2) || \ 213 | ((PRESCALER) == SPI_BaudRatePrescaler_4) || \ 214 | ((PRESCALER) == SPI_BaudRatePrescaler_8) || \ 215 | ((PRESCALER) == SPI_BaudRatePrescaler_16) || \ 216 | ((PRESCALER) == SPI_BaudRatePrescaler_32) || \ 217 | ((PRESCALER) == SPI_BaudRatePrescaler_64) || \ 218 | ((PRESCALER) == SPI_BaudRatePrescaler_128) || \ 219 | ((PRESCALER) == SPI_BaudRatePrescaler_256)) 220 | /** 221 | * @} 222 | */ 223 | 224 | /** @defgroup SPI_MSB_LSB_transmission 225 | * @{ 226 | */ 227 | 228 | #define SPI_FirstBit_MSB ((uint16_t)0x0000) 229 | #define SPI_FirstBit_LSB ((uint16_t)0x0080) 230 | #define IS_SPI_FIRST_BIT(BIT) (((BIT) == SPI_FirstBit_MSB) || \ 231 | ((BIT) == SPI_FirstBit_LSB)) 232 | /** 233 | * @} 234 | */ 235 | 236 | /** @defgroup I2S_Mode 237 | * @{ 238 | */ 239 | 240 | #define I2S_Mode_SlaveTx ((uint16_t)0x0000) 241 | #define I2S_Mode_SlaveRx ((uint16_t)0x0100) 242 | #define I2S_Mode_MasterTx ((uint16_t)0x0200) 243 | #define I2S_Mode_MasterRx ((uint16_t)0x0300) 244 | #define IS_I2S_MODE(MODE) (((MODE) == I2S_Mode_SlaveTx) || \ 245 | ((MODE) == I2S_Mode_SlaveRx) || \ 246 | ((MODE) == I2S_Mode_MasterTx) || \ 247 | ((MODE) == I2S_Mode_MasterRx) ) 248 | /** 249 | * @} 250 | */ 251 | 252 | /** @defgroup I2S_Standard 253 | * @{ 254 | */ 255 | 256 | #define I2S_Standard_Phillips ((uint16_t)0x0000) 257 | #define I2S_Standard_MSB ((uint16_t)0x0010) 258 | #define I2S_Standard_LSB ((uint16_t)0x0020) 259 | #define I2S_Standard_PCMShort ((uint16_t)0x0030) 260 | #define I2S_Standard_PCMLong ((uint16_t)0x00B0) 261 | #define IS_I2S_STANDARD(STANDARD) (((STANDARD) == I2S_Standard_Phillips) || \ 262 | ((STANDARD) == I2S_Standard_MSB) || \ 263 | ((STANDARD) == I2S_Standard_LSB) || \ 264 | ((STANDARD) == I2S_Standard_PCMShort) || \ 265 | ((STANDARD) == I2S_Standard_PCMLong)) 266 | /** 267 | * @} 268 | */ 269 | 270 | /** @defgroup I2S_Data_Format 271 | * @{ 272 | */ 273 | 274 | #define I2S_DataFormat_16b ((uint16_t)0x0000) 275 | #define I2S_DataFormat_16bextended ((uint16_t)0x0001) 276 | #define I2S_DataFormat_24b ((uint16_t)0x0003) 277 | #define I2S_DataFormat_32b ((uint16_t)0x0005) 278 | #define IS_I2S_DATA_FORMAT(FORMAT) (((FORMAT) == I2S_DataFormat_16b) || \ 279 | ((FORMAT) == I2S_DataFormat_16bextended) || \ 280 | ((FORMAT) == I2S_DataFormat_24b) || \ 281 | ((FORMAT) == I2S_DataFormat_32b)) 282 | /** 283 | * @} 284 | */ 285 | 286 | /** @defgroup I2S_MCLK_Output 287 | * @{ 288 | */ 289 | 290 | #define I2S_MCLKOutput_Enable ((uint16_t)0x0200) 291 | #define I2S_MCLKOutput_Disable ((uint16_t)0x0000) 292 | #define IS_I2S_MCLK_OUTPUT(OUTPUT) (((OUTPUT) == I2S_MCLKOutput_Enable) || \ 293 | ((OUTPUT) == I2S_MCLKOutput_Disable)) 294 | /** 295 | * @} 296 | */ 297 | 298 | /** @defgroup I2S_Audio_Frequency 299 | * @{ 300 | */ 301 | 302 | #define I2S_AudioFreq_192k ((uint32_t)192000) 303 | #define I2S_AudioFreq_96k ((uint32_t)96000) 304 | #define I2S_AudioFreq_48k ((uint32_t)48000) 305 | #define I2S_AudioFreq_44k ((uint32_t)44100) 306 | #define I2S_AudioFreq_32k ((uint32_t)32000) 307 | #define I2S_AudioFreq_22k ((uint32_t)22050) 308 | #define I2S_AudioFreq_16k ((uint32_t)16000) 309 | #define I2S_AudioFreq_11k ((uint32_t)11025) 310 | #define I2S_AudioFreq_8k ((uint32_t)8000) 311 | #define I2S_AudioFreq_Default ((uint32_t)2) 312 | 313 | #define IS_I2S_AUDIO_FREQ(FREQ) ((((FREQ) >= I2S_AudioFreq_8k) && \ 314 | ((FREQ) <= I2S_AudioFreq_192k)) || \ 315 | ((FREQ) == I2S_AudioFreq_Default)) 316 | /** 317 | * @} 318 | */ 319 | 320 | /** @defgroup I2S_Clock_Polarity 321 | * @{ 322 | */ 323 | 324 | #define I2S_CPOL_Low ((uint16_t)0x0000) 325 | #define I2S_CPOL_High ((uint16_t)0x0008) 326 | #define IS_I2S_CPOL(CPOL) (((CPOL) == I2S_CPOL_Low) || \ 327 | ((CPOL) == I2S_CPOL_High)) 328 | /** 329 | * @} 330 | */ 331 | 332 | /** @defgroup SPI_I2S_DMA_transfer_requests 333 | * @{ 334 | */ 335 | 336 | #define SPI_I2S_DMAReq_Tx ((uint16_t)0x0002) 337 | #define SPI_I2S_DMAReq_Rx ((uint16_t)0x0001) 338 | #define IS_SPI_I2S_DMAREQ(DMAREQ) ((((DMAREQ) & (uint16_t)0xFFFC) == 0x00) && ((DMAREQ) != 0x00)) 339 | /** 340 | * @} 341 | */ 342 | 343 | /** @defgroup SPI_NSS_internal_software_management 344 | * @{ 345 | */ 346 | 347 | #define SPI_NSSInternalSoft_Set ((uint16_t)0x0100) 348 | #define SPI_NSSInternalSoft_Reset ((uint16_t)0xFEFF) 349 | #define IS_SPI_NSS_INTERNAL(INTERNAL) (((INTERNAL) == SPI_NSSInternalSoft_Set) || \ 350 | ((INTERNAL) == SPI_NSSInternalSoft_Reset)) 351 | /** 352 | * @} 353 | */ 354 | 355 | /** @defgroup SPI_CRC_Transmit_Receive 356 | * @{ 357 | */ 358 | 359 | #define SPI_CRC_Tx ((uint8_t)0x00) 360 | #define SPI_CRC_Rx ((uint8_t)0x01) 361 | #define IS_SPI_CRC(CRC) (((CRC) == SPI_CRC_Tx) || ((CRC) == SPI_CRC_Rx)) 362 | /** 363 | * @} 364 | */ 365 | 366 | /** @defgroup SPI_direction_transmit_receive 367 | * @{ 368 | */ 369 | 370 | #define SPI_Direction_Rx ((uint16_t)0xBFFF) 371 | #define SPI_Direction_Tx ((uint16_t)0x4000) 372 | #define IS_SPI_DIRECTION(DIRECTION) (((DIRECTION) == SPI_Direction_Rx) || \ 373 | ((DIRECTION) == SPI_Direction_Tx)) 374 | /** 375 | * @} 376 | */ 377 | 378 | /** @defgroup SPI_I2S_interrupts_definition 379 | * @{ 380 | */ 381 | 382 | #define SPI_I2S_IT_TXE ((uint8_t)0x71) 383 | #define SPI_I2S_IT_RXNE ((uint8_t)0x60) 384 | #define SPI_I2S_IT_ERR ((uint8_t)0x50) 385 | #define IS_SPI_I2S_CONFIG_IT(IT) (((IT) == SPI_I2S_IT_TXE) || \ 386 | ((IT) == SPI_I2S_IT_RXNE) || \ 387 | ((IT) == SPI_I2S_IT_ERR)) 388 | #define SPI_I2S_IT_OVR ((uint8_t)0x56) 389 | #define SPI_IT_MODF ((uint8_t)0x55) 390 | #define SPI_IT_CRCERR ((uint8_t)0x54) 391 | #define I2S_IT_UDR ((uint8_t)0x53) 392 | #define IS_SPI_I2S_CLEAR_IT(IT) (((IT) == SPI_IT_CRCERR)) 393 | #define IS_SPI_I2S_GET_IT(IT) (((IT) == SPI_I2S_IT_RXNE) || ((IT) == SPI_I2S_IT_TXE) || \ 394 | ((IT) == I2S_IT_UDR) || ((IT) == SPI_IT_CRCERR) || \ 395 | ((IT) == SPI_IT_MODF) || ((IT) == SPI_I2S_IT_OVR)) 396 | /** 397 | * @} 398 | */ 399 | 400 | /** @defgroup SPI_I2S_flags_definition 401 | * @{ 402 | */ 403 | 404 | #define SPI_I2S_FLAG_RXNE ((uint16_t)0x0001) 405 | #define SPI_I2S_FLAG_TXE ((uint16_t)0x0002) 406 | #define I2S_FLAG_CHSIDE ((uint16_t)0x0004) 407 | #define I2S_FLAG_UDR ((uint16_t)0x0008) 408 | #define SPI_FLAG_CRCERR ((uint16_t)0x0010) 409 | #define SPI_FLAG_MODF ((uint16_t)0x0020) 410 | #define SPI_I2S_FLAG_OVR ((uint16_t)0x0040) 411 | #define SPI_I2S_FLAG_BSY ((uint16_t)0x0080) 412 | #define IS_SPI_I2S_CLEAR_FLAG(FLAG) (((FLAG) == SPI_FLAG_CRCERR)) 413 | #define IS_SPI_I2S_GET_FLAG(FLAG) (((FLAG) == SPI_I2S_FLAG_BSY) || ((FLAG) == SPI_I2S_FLAG_OVR) || \ 414 | ((FLAG) == SPI_FLAG_MODF) || ((FLAG) == SPI_FLAG_CRCERR) || \ 415 | ((FLAG) == I2S_FLAG_UDR) || ((FLAG) == I2S_FLAG_CHSIDE) || \ 416 | ((FLAG) == SPI_I2S_FLAG_TXE) || ((FLAG) == SPI_I2S_FLAG_RXNE)) 417 | /** 418 | * @} 419 | */ 420 | 421 | /** @defgroup SPI_CRC_polynomial 422 | * @{ 423 | */ 424 | 425 | #define IS_SPI_CRC_POLYNOMIAL(POLYNOMIAL) ((POLYNOMIAL) >= 0x1) 426 | /** 427 | * @} 428 | */ 429 | 430 | /** 431 | * @} 432 | */ 433 | 434 | /** @defgroup SPI_Exported_Macros 435 | * @{ 436 | */ 437 | 438 | /** 439 | * @} 440 | */ 441 | 442 | /** @defgroup SPI_Exported_Functions 443 | * @{ 444 | */ 445 | 446 | void SPI_I2S_DeInit(SPI_TypeDef* SPIx); 447 | void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct); 448 | void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct); 449 | void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct); 450 | void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct); 451 | void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState); 452 | void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState); 453 | void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState); 454 | void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState); 455 | void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data); 456 | uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx); 457 | void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft); 458 | void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState); 459 | void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize); 460 | void SPI_TransmitCRC(SPI_TypeDef* SPIx); 461 | void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState); 462 | uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC); 463 | uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx); 464 | void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction); 465 | FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG); 466 | void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG); 467 | ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT); 468 | void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT); 469 | 470 | #ifdef __cplusplus 471 | } 472 | #endif 473 | 474 | #endif /*__STM32F10x_SPI_H */ 475 | /** 476 | * @} 477 | */ 478 | 479 | /** 480 | * @} 481 | */ 482 | 483 | /** 484 | * @} 485 | */ 486 | 487 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 488 | -------------------------------------------------------------------------------- /stm_lib/inc/stm32f10x_usart.h: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f10x_usart.h 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 11-March-2011 7 | * @brief This file contains all the functions prototypes for the USART 8 | * firmware library. 9 | ****************************************************************************** 10 | * @attention 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 | *

© COPYRIGHT 2011 STMicroelectronics

20 | ****************************************************************************** 21 | */ 22 | 23 | /* Define to prevent recursive inclusion -------------------------------------*/ 24 | #ifndef __STM32F10x_USART_H 25 | #define __STM32F10x_USART_H 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif 30 | 31 | /* Includes ------------------------------------------------------------------*/ 32 | #include "stm32f10x.h" 33 | 34 | /** @addtogroup STM32F10x_StdPeriph_Driver 35 | * @{ 36 | */ 37 | 38 | /** @addtogroup USART 39 | * @{ 40 | */ 41 | 42 | /** @defgroup USART_Exported_Types 43 | * @{ 44 | */ 45 | 46 | /** 47 | * @brief USART Init Structure definition 48 | */ 49 | 50 | typedef struct 51 | { 52 | uint32_t USART_BaudRate; /*!< This member configures the USART communication baud rate. 53 | The baud rate is computed using the following formula: 54 | - IntegerDivider = ((PCLKx) / (16 * (USART_InitStruct->USART_BaudRate))) 55 | - FractionalDivider = ((IntegerDivider - ((u32) IntegerDivider)) * 16) + 0.5 */ 56 | 57 | uint16_t USART_WordLength; /*!< Specifies the number of data bits transmitted or received in a frame. 58 | This parameter can be a value of @ref USART_Word_Length */ 59 | 60 | uint16_t USART_StopBits; /*!< Specifies the number of stop bits transmitted. 61 | This parameter can be a value of @ref USART_Stop_Bits */ 62 | 63 | uint16_t USART_Parity; /*!< Specifies the parity mode. 64 | This parameter can be a value of @ref USART_Parity 65 | @note When parity is enabled, the computed parity is inserted 66 | at the MSB position of the transmitted data (9th bit when 67 | the word length is set to 9 data bits; 8th bit when the 68 | word length is set to 8 data bits). */ 69 | 70 | uint16_t USART_Mode; /*!< Specifies wether the Receive or Transmit mode is enabled or disabled. 71 | This parameter can be a value of @ref USART_Mode */ 72 | 73 | uint16_t USART_HardwareFlowControl; /*!< Specifies wether the hardware flow control mode is enabled 74 | or disabled. 75 | This parameter can be a value of @ref USART_Hardware_Flow_Control */ 76 | } USART_InitTypeDef; 77 | 78 | /** 79 | * @brief USART Clock Init Structure definition 80 | */ 81 | 82 | typedef struct 83 | { 84 | 85 | uint16_t USART_Clock; /*!< Specifies whether the USART clock is enabled or disabled. 86 | This parameter can be a value of @ref USART_Clock */ 87 | 88 | uint16_t USART_CPOL; /*!< Specifies the steady state value of the serial clock. 89 | This parameter can be a value of @ref USART_Clock_Polarity */ 90 | 91 | uint16_t USART_CPHA; /*!< Specifies the clock transition on which the bit capture is made. 92 | This parameter can be a value of @ref USART_Clock_Phase */ 93 | 94 | uint16_t USART_LastBit; /*!< Specifies whether the clock pulse corresponding to the last transmitted 95 | data bit (MSB) has to be output on the SCLK pin in synchronous mode. 96 | This parameter can be a value of @ref USART_Last_Bit */ 97 | } USART_ClockInitTypeDef; 98 | 99 | /** 100 | * @} 101 | */ 102 | 103 | /** @defgroup USART_Exported_Constants 104 | * @{ 105 | */ 106 | 107 | #define IS_USART_ALL_PERIPH(PERIPH) (((PERIPH) == USART1) || \ 108 | ((PERIPH) == USART2) || \ 109 | ((PERIPH) == USART3) || \ 110 | ((PERIPH) == UART4) || \ 111 | ((PERIPH) == UART5)) 112 | 113 | #define IS_USART_123_PERIPH(PERIPH) (((PERIPH) == USART1) || \ 114 | ((PERIPH) == USART2) || \ 115 | ((PERIPH) == USART3)) 116 | 117 | #define IS_USART_1234_PERIPH(PERIPH) (((PERIPH) == USART1) || \ 118 | ((PERIPH) == USART2) || \ 119 | ((PERIPH) == USART3) || \ 120 | ((PERIPH) == UART4)) 121 | /** @defgroup USART_Word_Length 122 | * @{ 123 | */ 124 | 125 | #define USART_WordLength_8b ((uint16_t)0x0000) 126 | #define USART_WordLength_9b ((uint16_t)0x1000) 127 | 128 | #define IS_USART_WORD_LENGTH(LENGTH) (((LENGTH) == USART_WordLength_8b) || \ 129 | ((LENGTH) == USART_WordLength_9b)) 130 | /** 131 | * @} 132 | */ 133 | 134 | /** @defgroup USART_Stop_Bits 135 | * @{ 136 | */ 137 | 138 | #define USART_StopBits_1 ((uint16_t)0x0000) 139 | #define USART_StopBits_0_5 ((uint16_t)0x1000) 140 | #define USART_StopBits_2 ((uint16_t)0x2000) 141 | #define USART_StopBits_1_5 ((uint16_t)0x3000) 142 | #define IS_USART_STOPBITS(STOPBITS) (((STOPBITS) == USART_StopBits_1) || \ 143 | ((STOPBITS) == USART_StopBits_0_5) || \ 144 | ((STOPBITS) == USART_StopBits_2) || \ 145 | ((STOPBITS) == USART_StopBits_1_5)) 146 | /** 147 | * @} 148 | */ 149 | 150 | /** @defgroup USART_Parity 151 | * @{ 152 | */ 153 | 154 | #define USART_Parity_No ((uint16_t)0x0000) 155 | #define USART_Parity_Even ((uint16_t)0x0400) 156 | #define USART_Parity_Odd ((uint16_t)0x0600) 157 | #define IS_USART_PARITY(PARITY) (((PARITY) == USART_Parity_No) || \ 158 | ((PARITY) == USART_Parity_Even) || \ 159 | ((PARITY) == USART_Parity_Odd)) 160 | /** 161 | * @} 162 | */ 163 | 164 | /** @defgroup USART_Mode 165 | * @{ 166 | */ 167 | 168 | #define USART_Mode_Rx ((uint16_t)0x0004) 169 | #define USART_Mode_Tx ((uint16_t)0x0008) 170 | #define IS_USART_MODE(MODE) ((((MODE) & (uint16_t)0xFFF3) == 0x00) && ((MODE) != (uint16_t)0x00)) 171 | /** 172 | * @} 173 | */ 174 | 175 | /** @defgroup USART_Hardware_Flow_Control 176 | * @{ 177 | */ 178 | #define USART_HardwareFlowControl_None ((uint16_t)0x0000) 179 | #define USART_HardwareFlowControl_RTS ((uint16_t)0x0100) 180 | #define USART_HardwareFlowControl_CTS ((uint16_t)0x0200) 181 | #define USART_HardwareFlowControl_RTS_CTS ((uint16_t)0x0300) 182 | #define IS_USART_HARDWARE_FLOW_CONTROL(CONTROL)\ 183 | (((CONTROL) == USART_HardwareFlowControl_None) || \ 184 | ((CONTROL) == USART_HardwareFlowControl_RTS) || \ 185 | ((CONTROL) == USART_HardwareFlowControl_CTS) || \ 186 | ((CONTROL) == USART_HardwareFlowControl_RTS_CTS)) 187 | /** 188 | * @} 189 | */ 190 | 191 | /** @defgroup USART_Clock 192 | * @{ 193 | */ 194 | #define USART_Clock_Disable ((uint16_t)0x0000) 195 | #define USART_Clock_Enable ((uint16_t)0x0800) 196 | #define IS_USART_CLOCK(CLOCK) (((CLOCK) == USART_Clock_Disable) || \ 197 | ((CLOCK) == USART_Clock_Enable)) 198 | /** 199 | * @} 200 | */ 201 | 202 | /** @defgroup USART_Clock_Polarity 203 | * @{ 204 | */ 205 | 206 | #define USART_CPOL_Low ((uint16_t)0x0000) 207 | #define USART_CPOL_High ((uint16_t)0x0400) 208 | #define IS_USART_CPOL(CPOL) (((CPOL) == USART_CPOL_Low) || ((CPOL) == USART_CPOL_High)) 209 | 210 | /** 211 | * @} 212 | */ 213 | 214 | /** @defgroup USART_Clock_Phase 215 | * @{ 216 | */ 217 | 218 | #define USART_CPHA_1Edge ((uint16_t)0x0000) 219 | #define USART_CPHA_2Edge ((uint16_t)0x0200) 220 | #define IS_USART_CPHA(CPHA) (((CPHA) == USART_CPHA_1Edge) || ((CPHA) == USART_CPHA_2Edge)) 221 | 222 | /** 223 | * @} 224 | */ 225 | 226 | /** @defgroup USART_Last_Bit 227 | * @{ 228 | */ 229 | 230 | #define USART_LastBit_Disable ((uint16_t)0x0000) 231 | #define USART_LastBit_Enable ((uint16_t)0x0100) 232 | #define IS_USART_LASTBIT(LASTBIT) (((LASTBIT) == USART_LastBit_Disable) || \ 233 | ((LASTBIT) == USART_LastBit_Enable)) 234 | /** 235 | * @} 236 | */ 237 | 238 | /** @defgroup USART_Interrupt_definition 239 | * @{ 240 | */ 241 | 242 | #define USART_IT_PE ((uint16_t)0x0028) 243 | #define USART_IT_TXE ((uint16_t)0x0727) 244 | #define USART_IT_TC ((uint16_t)0x0626) 245 | #define USART_IT_RXNE ((uint16_t)0x0525) 246 | #define USART_IT_IDLE ((uint16_t)0x0424) 247 | #define USART_IT_LBD ((uint16_t)0x0846) 248 | #define USART_IT_CTS ((uint16_t)0x096A) 249 | #define USART_IT_ERR ((uint16_t)0x0060) 250 | #define USART_IT_ORE ((uint16_t)0x0360) 251 | #define USART_IT_NE ((uint16_t)0x0260) 252 | #define USART_IT_FE ((uint16_t)0x0160) 253 | #define IS_USART_CONFIG_IT(IT) (((IT) == USART_IT_PE) || ((IT) == USART_IT_TXE) || \ 254 | ((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \ 255 | ((IT) == USART_IT_IDLE) || ((IT) == USART_IT_LBD) || \ 256 | ((IT) == USART_IT_CTS) || ((IT) == USART_IT_ERR)) 257 | #define IS_USART_GET_IT(IT) (((IT) == USART_IT_PE) || ((IT) == USART_IT_TXE) || \ 258 | ((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \ 259 | ((IT) == USART_IT_IDLE) || ((IT) == USART_IT_LBD) || \ 260 | ((IT) == USART_IT_CTS) || ((IT) == USART_IT_ORE) || \ 261 | ((IT) == USART_IT_NE) || ((IT) == USART_IT_FE)) 262 | #define IS_USART_CLEAR_IT(IT) (((IT) == USART_IT_TC) || ((IT) == USART_IT_RXNE) || \ 263 | ((IT) == USART_IT_LBD) || ((IT) == USART_IT_CTS)) 264 | /** 265 | * @} 266 | */ 267 | 268 | /** @defgroup USART_DMA_Requests 269 | * @{ 270 | */ 271 | 272 | #define USART_DMAReq_Tx ((uint16_t)0x0080) 273 | #define USART_DMAReq_Rx ((uint16_t)0x0040) 274 | #define IS_USART_DMAREQ(DMAREQ) ((((DMAREQ) & (uint16_t)0xFF3F) == 0x00) && ((DMAREQ) != (uint16_t)0x00)) 275 | 276 | /** 277 | * @} 278 | */ 279 | 280 | /** @defgroup USART_WakeUp_methods 281 | * @{ 282 | */ 283 | 284 | #define USART_WakeUp_IdleLine ((uint16_t)0x0000) 285 | #define USART_WakeUp_AddressMark ((uint16_t)0x0800) 286 | #define IS_USART_WAKEUP(WAKEUP) (((WAKEUP) == USART_WakeUp_IdleLine) || \ 287 | ((WAKEUP) == USART_WakeUp_AddressMark)) 288 | /** 289 | * @} 290 | */ 291 | 292 | /** @defgroup USART_LIN_Break_Detection_Length 293 | * @{ 294 | */ 295 | 296 | #define USART_LINBreakDetectLength_10b ((uint16_t)0x0000) 297 | #define USART_LINBreakDetectLength_11b ((uint16_t)0x0020) 298 | #define IS_USART_LIN_BREAK_DETECT_LENGTH(LENGTH) \ 299 | (((LENGTH) == USART_LINBreakDetectLength_10b) || \ 300 | ((LENGTH) == USART_LINBreakDetectLength_11b)) 301 | /** 302 | * @} 303 | */ 304 | 305 | /** @defgroup USART_IrDA_Low_Power 306 | * @{ 307 | */ 308 | 309 | #define USART_IrDAMode_LowPower ((uint16_t)0x0004) 310 | #define USART_IrDAMode_Normal ((uint16_t)0x0000) 311 | #define IS_USART_IRDA_MODE(MODE) (((MODE) == USART_IrDAMode_LowPower) || \ 312 | ((MODE) == USART_IrDAMode_Normal)) 313 | /** 314 | * @} 315 | */ 316 | 317 | /** @defgroup USART_Flags 318 | * @{ 319 | */ 320 | 321 | #define USART_FLAG_CTS ((uint16_t)0x0200) 322 | #define USART_FLAG_LBD ((uint16_t)0x0100) 323 | #define USART_FLAG_TXE ((uint16_t)0x0080) 324 | #define USART_FLAG_TC ((uint16_t)0x0040) 325 | #define USART_FLAG_RXNE ((uint16_t)0x0020) 326 | #define USART_FLAG_IDLE ((uint16_t)0x0010) 327 | #define USART_FLAG_ORE ((uint16_t)0x0008) 328 | #define USART_FLAG_NE ((uint16_t)0x0004) 329 | #define USART_FLAG_FE ((uint16_t)0x0002) 330 | #define USART_FLAG_PE ((uint16_t)0x0001) 331 | #define IS_USART_FLAG(FLAG) (((FLAG) == USART_FLAG_PE) || ((FLAG) == USART_FLAG_TXE) || \ 332 | ((FLAG) == USART_FLAG_TC) || ((FLAG) == USART_FLAG_RXNE) || \ 333 | ((FLAG) == USART_FLAG_IDLE) || ((FLAG) == USART_FLAG_LBD) || \ 334 | ((FLAG) == USART_FLAG_CTS) || ((FLAG) == USART_FLAG_ORE) || \ 335 | ((FLAG) == USART_FLAG_NE) || ((FLAG) == USART_FLAG_FE)) 336 | 337 | #define IS_USART_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0xFC9F) == 0x00) && ((FLAG) != (uint16_t)0x00)) 338 | #define IS_USART_PERIPH_FLAG(PERIPH, USART_FLAG) ((((*(uint32_t*)&(PERIPH)) != UART4_BASE) &&\ 339 | ((*(uint32_t*)&(PERIPH)) != UART5_BASE)) \ 340 | || ((USART_FLAG) != USART_FLAG_CTS)) 341 | #define IS_USART_BAUDRATE(BAUDRATE) (((BAUDRATE) > 0) && ((BAUDRATE) < 0x0044AA21)) 342 | #define IS_USART_ADDRESS(ADDRESS) ((ADDRESS) <= 0xF) 343 | #define IS_USART_DATA(DATA) ((DATA) <= 0x1FF) 344 | 345 | /** 346 | * @} 347 | */ 348 | 349 | /** 350 | * @} 351 | */ 352 | 353 | /** @defgroup USART_Exported_Macros 354 | * @{ 355 | */ 356 | 357 | /** 358 | * @} 359 | */ 360 | 361 | /** @defgroup USART_Exported_Functions 362 | * @{ 363 | */ 364 | 365 | void USART_DeInit(USART_TypeDef* USARTx); 366 | void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct); 367 | void USART_StructInit(USART_InitTypeDef* USART_InitStruct); 368 | void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct); 369 | void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct); 370 | void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState); 371 | void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState); 372 | void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState); 373 | void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address); 374 | void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp); 375 | void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState); 376 | void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t USART_LINBreakDetectLength); 377 | void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState); 378 | void USART_SendData(USART_TypeDef* USARTx, uint16_t Data); 379 | uint16_t USART_ReceiveData(USART_TypeDef* USARTx); 380 | void USART_SendBreak(USART_TypeDef* USARTx); 381 | void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime); 382 | void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler); 383 | void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState); 384 | void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState); 385 | void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState); 386 | void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState); 387 | void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState); 388 | void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode); 389 | void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState); 390 | FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG); 391 | void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG); 392 | ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT); 393 | void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT); 394 | 395 | #ifdef __cplusplus 396 | } 397 | #endif 398 | 399 | #endif /* __STM32F10x_USART_H */ 400 | /** 401 | * @} 402 | */ 403 | 404 | /** 405 | * @} 406 | */ 407 | 408 | /** 409 | * @} 410 | */ 411 | 412 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 413 | -------------------------------------------------------------------------------- /stm_lib/src/.readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /stm_lib/src/misc.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file misc.c 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 11-March-2011 7 | * @brief This file provides all the miscellaneous firmware functions (add-on 8 | * to CMSIS functions). 9 | ****************************************************************************** 10 | * @attention 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 | *

© COPYRIGHT 2011 STMicroelectronics

20 | ****************************************************************************** 21 | */ 22 | 23 | /* Includes ------------------------------------------------------------------*/ 24 | #include "misc.h" 25 | 26 | /** @addtogroup STM32F10x_StdPeriph_Driver 27 | * @{ 28 | */ 29 | 30 | /** @defgroup MISC 31 | * @brief MISC driver modules 32 | * @{ 33 | */ 34 | 35 | /** @defgroup MISC_Private_TypesDefinitions 36 | * @{ 37 | */ 38 | 39 | /** 40 | * @} 41 | */ 42 | 43 | /** @defgroup MISC_Private_Defines 44 | * @{ 45 | */ 46 | 47 | #define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000) 48 | /** 49 | * @} 50 | */ 51 | 52 | /** @defgroup MISC_Private_Macros 53 | * @{ 54 | */ 55 | 56 | /** 57 | * @} 58 | */ 59 | 60 | /** @defgroup MISC_Private_Variables 61 | * @{ 62 | */ 63 | 64 | /** 65 | * @} 66 | */ 67 | 68 | /** @defgroup MISC_Private_FunctionPrototypes 69 | * @{ 70 | */ 71 | 72 | /** 73 | * @} 74 | */ 75 | 76 | /** @defgroup MISC_Private_Functions 77 | * @{ 78 | */ 79 | 80 | /** 81 | * @brief Configures the priority grouping: pre-emption priority and subpriority. 82 | * @param NVIC_PriorityGroup: specifies the priority grouping bits length. 83 | * This parameter can be one of the following values: 84 | * @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority 85 | * 4 bits for subpriority 86 | * @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority 87 | * 3 bits for subpriority 88 | * @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority 89 | * 2 bits for subpriority 90 | * @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority 91 | * 1 bits for subpriority 92 | * @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority 93 | * 0 bits for subpriority 94 | * @retval None 95 | */ 96 | void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup) 97 | { 98 | /* Check the parameters */ 99 | assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup)); 100 | 101 | /* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */ 102 | SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup; 103 | } 104 | 105 | /** 106 | * @brief Initializes the NVIC peripheral according to the specified 107 | * parameters in the NVIC_InitStruct. 108 | * @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains 109 | * the configuration information for the specified NVIC peripheral. 110 | * @retval None 111 | */ 112 | void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct) 113 | { 114 | uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F; 115 | 116 | /* Check the parameters */ 117 | assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd)); 118 | assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority)); 119 | assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority)); 120 | 121 | if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE) 122 | { 123 | /* Compute the Corresponding IRQ Priority --------------------------------*/ 124 | tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08; 125 | tmppre = (0x4 - tmppriority); 126 | tmpsub = tmpsub >> tmppriority; 127 | 128 | tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre; 129 | tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub; 130 | tmppriority = tmppriority << 0x04; 131 | 132 | NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority; 133 | 134 | /* Enable the Selected IRQ Channels --------------------------------------*/ 135 | NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = 136 | (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); 137 | } 138 | else 139 | { 140 | /* Disable the Selected IRQ Channels -------------------------------------*/ 141 | NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] = 142 | (uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F); 143 | } 144 | } 145 | 146 | /** 147 | * @brief Sets the vector table location and Offset. 148 | * @param NVIC_VectTab: specifies if the vector table is in RAM or FLASH memory. 149 | * This parameter can be one of the following values: 150 | * @arg NVIC_VectTab_RAM 151 | * @arg NVIC_VectTab_FLASH 152 | * @param Offset: Vector Table base offset field. This value must be a multiple 153 | * of 0x200. 154 | * @retval None 155 | */ 156 | void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset) 157 | { 158 | /* Check the parameters */ 159 | assert_param(IS_NVIC_VECTTAB(NVIC_VectTab)); 160 | assert_param(IS_NVIC_OFFSET(Offset)); 161 | 162 | SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80); 163 | } 164 | 165 | /** 166 | * @brief Selects the condition for the system to enter low power mode. 167 | * @param LowPowerMode: Specifies the new mode for the system to enter low power mode. 168 | * This parameter can be one of the following values: 169 | * @arg NVIC_LP_SEVONPEND 170 | * @arg NVIC_LP_SLEEPDEEP 171 | * @arg NVIC_LP_SLEEPONEXIT 172 | * @param NewState: new state of LP condition. This parameter can be: ENABLE or DISABLE. 173 | * @retval None 174 | */ 175 | void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState) 176 | { 177 | /* Check the parameters */ 178 | assert_param(IS_NVIC_LP(LowPowerMode)); 179 | assert_param(IS_FUNCTIONAL_STATE(NewState)); 180 | 181 | if (NewState != DISABLE) 182 | { 183 | SCB->SCR |= LowPowerMode; 184 | } 185 | else 186 | { 187 | SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode); 188 | } 189 | } 190 | 191 | /** 192 | * @brief Configures the SysTick clock source. 193 | * @param SysTick_CLKSource: specifies the SysTick clock source. 194 | * This parameter can be one of the following values: 195 | * @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source. 196 | * @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source. 197 | * @retval None 198 | */ 199 | void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource) 200 | { 201 | /* Check the parameters */ 202 | assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource)); 203 | if (SysTick_CLKSource == SysTick_CLKSource_HCLK) 204 | { 205 | SysTick->CTRL |= SysTick_CLKSource_HCLK; 206 | } 207 | else 208 | { 209 | SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8; 210 | } 211 | } 212 | 213 | /** 214 | * @} 215 | */ 216 | 217 | /** 218 | * @} 219 | */ 220 | 221 | /** 222 | * @} 223 | */ 224 | 225 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 226 | -------------------------------------------------------------------------------- /stm_lib/src/stm32f10x_flash.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darksidelemm/RS41FOX/9a4e4137032302171b62b3976e8ceb72193e5ecc/stm_lib/src/stm32f10x_flash.c -------------------------------------------------------------------------------- /stm_lib/src/stm32f10x_pwr.c: -------------------------------------------------------------------------------- 1 | /** 2 | ****************************************************************************** 3 | * @file stm32f10x_pwr.c 4 | * @author MCD Application Team 5 | * @version V3.5.0 6 | * @date 11-March-2011 7 | * @brief This file provides all the PWR firmware functions. 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 | /* Includes ------------------------------------------------------------------*/ 23 | #include "stm32f10x_pwr.h" 24 | #include "stm32f10x_rcc.h" 25 | 26 | /** @addtogroup STM32F10x_StdPeriph_Driver 27 | * @{ 28 | */ 29 | 30 | /** @defgroup PWR 31 | * @brief PWR driver modules 32 | * @{ 33 | */ 34 | 35 | /** @defgroup PWR_Private_TypesDefinitions 36 | * @{ 37 | */ 38 | 39 | /** 40 | * @} 41 | */ 42 | 43 | /** @defgroup PWR_Private_Defines 44 | * @{ 45 | */ 46 | 47 | /* --------- PWR registers bit address in the alias region ---------- */ 48 | #define PWR_OFFSET (PWR_BASE - PERIPH_BASE) 49 | 50 | /* --- CR Register ---*/ 51 | 52 | /* Alias word address of DBP bit */ 53 | #define CR_OFFSET (PWR_OFFSET + 0x00) 54 | #define DBP_BitNumber 0x08 55 | #define CR_DBP_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (DBP_BitNumber * 4)) 56 | 57 | /* Alias word address of PVDE bit */ 58 | #define PVDE_BitNumber 0x04 59 | #define CR_PVDE_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PVDE_BitNumber * 4)) 60 | 61 | /* --- CSR Register ---*/ 62 | 63 | /* Alias word address of EWUP bit */ 64 | #define CSR_OFFSET (PWR_OFFSET + 0x04) 65 | #define EWUP_BitNumber 0x08 66 | #define CSR_EWUP_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (EWUP_BitNumber * 4)) 67 | 68 | /* ------------------ PWR registers bit mask ------------------------ */ 69 | 70 | /* CR register bit mask */ 71 | #define CR_DS_MASK ((uint32_t)0xFFFFFFFC) 72 | #define CR_PLS_MASK ((uint32_t)0xFFFFFF1F) 73 | 74 | 75 | /** 76 | * @} 77 | */ 78 | 79 | /** @defgroup PWR_Private_Macros 80 | * @{ 81 | */ 82 | 83 | /** 84 | * @} 85 | */ 86 | 87 | /** @defgroup PWR_Private_Variables 88 | * @{ 89 | */ 90 | 91 | /** 92 | * @} 93 | */ 94 | 95 | /** @defgroup PWR_Private_FunctionPrototypes 96 | * @{ 97 | */ 98 | 99 | /** 100 | * @} 101 | */ 102 | 103 | /** @defgroup PWR_Private_Functions 104 | * @{ 105 | */ 106 | 107 | /** 108 | * @brief Deinitializes the PWR peripheral registers to their default reset values. 109 | * @param None 110 | * @retval None 111 | */ 112 | void PWR_DeInit(void) 113 | { 114 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, ENABLE); 115 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, DISABLE); 116 | } 117 | 118 | /** 119 | * @brief Enables or disables access to the RTC and backup registers. 120 | * @param NewState: new state of the access to the RTC and backup registers. 121 | * This parameter can be: ENABLE or DISABLE. 122 | * @retval None 123 | */ 124 | void PWR_BackupAccessCmd(FunctionalState NewState) 125 | { 126 | /* Check the parameters */ 127 | assert_param(IS_FUNCTIONAL_STATE(NewState)); 128 | *(__IO uint32_t *) CR_DBP_BB = (uint32_t)NewState; 129 | } 130 | 131 | /** 132 | * @brief Enables or disables the Power Voltage Detector(PVD). 133 | * @param NewState: new state of the PVD. 134 | * This parameter can be: ENABLE or DISABLE. 135 | * @retval None 136 | */ 137 | void PWR_PVDCmd(FunctionalState NewState) 138 | { 139 | /* Check the parameters */ 140 | assert_param(IS_FUNCTIONAL_STATE(NewState)); 141 | *(__IO uint32_t *) CR_PVDE_BB = (uint32_t)NewState; 142 | } 143 | 144 | /** 145 | * @brief Configures the voltage threshold detected by the Power Voltage Detector(PVD). 146 | * @param PWR_PVDLevel: specifies the PVD detection level 147 | * This parameter can be one of the following values: 148 | * @arg PWR_PVDLevel_2V2: PVD detection level set to 2.2V 149 | * @arg PWR_PVDLevel_2V3: PVD detection level set to 2.3V 150 | * @arg PWR_PVDLevel_2V4: PVD detection level set to 2.4V 151 | * @arg PWR_PVDLevel_2V5: PVD detection level set to 2.5V 152 | * @arg PWR_PVDLevel_2V6: PVD detection level set to 2.6V 153 | * @arg PWR_PVDLevel_2V7: PVD detection level set to 2.7V 154 | * @arg PWR_PVDLevel_2V8: PVD detection level set to 2.8V 155 | * @arg PWR_PVDLevel_2V9: PVD detection level set to 2.9V 156 | * @retval None 157 | */ 158 | void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel) 159 | { 160 | uint32_t tmpreg = 0; 161 | /* Check the parameters */ 162 | assert_param(IS_PWR_PVD_LEVEL(PWR_PVDLevel)); 163 | tmpreg = PWR->CR; 164 | /* Clear PLS[7:5] bits */ 165 | tmpreg &= CR_PLS_MASK; 166 | /* Set PLS[7:5] bits according to PWR_PVDLevel value */ 167 | tmpreg |= PWR_PVDLevel; 168 | /* Store the new value */ 169 | PWR->CR = tmpreg; 170 | } 171 | 172 | /** 173 | * @brief Enables or disables the WakeUp Pin functionality. 174 | * @param NewState: new state of the WakeUp Pin functionality. 175 | * This parameter can be: ENABLE or DISABLE. 176 | * @retval None 177 | */ 178 | void PWR_WakeUpPinCmd(FunctionalState NewState) 179 | { 180 | /* Check the parameters */ 181 | assert_param(IS_FUNCTIONAL_STATE(NewState)); 182 | *(__IO uint32_t *) CSR_EWUP_BB = (uint32_t)NewState; 183 | } 184 | 185 | /** 186 | * @brief Enters STOP mode. 187 | * @param PWR_Regulator: specifies the regulator state in STOP mode. 188 | * This parameter can be one of the following values: 189 | * @arg PWR_Regulator_ON: STOP mode with regulator ON 190 | * @arg PWR_Regulator_LowPower: STOP mode with regulator in low power mode 191 | * @param PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction. 192 | * This parameter can be one of the following values: 193 | * @arg PWR_STOPEntry_WFI: enter STOP mode with WFI instruction 194 | * @arg PWR_STOPEntry_WFE: enter STOP mode with WFE instruction 195 | * @retval None 196 | */ 197 | void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry) 198 | { 199 | uint32_t tmpreg = 0; 200 | /* Check the parameters */ 201 | assert_param(IS_PWR_REGULATOR(PWR_Regulator)); 202 | assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry)); 203 | 204 | /* Select the regulator state in STOP mode ---------------------------------*/ 205 | tmpreg = PWR->CR; 206 | /* Clear PDDS and LPDS bits */ 207 | tmpreg &= CR_DS_MASK; 208 | /* Set LPDS bit according to PWR_Regulator value */ 209 | tmpreg |= PWR_Regulator; 210 | /* Store the new value */ 211 | PWR->CR = tmpreg; 212 | /* Set SLEEPDEEP bit of Cortex System Control Register */ 213 | SCB->SCR |= SCB_SCR_SLEEPDEEP; 214 | 215 | /* Select STOP mode entry --------------------------------------------------*/ 216 | if(PWR_STOPEntry == PWR_STOPEntry_WFI) 217 | { 218 | /* Request Wait For Interrupt */ 219 | __WFI(); 220 | } 221 | else 222 | { 223 | /* Request Wait For Event */ 224 | __WFE(); 225 | } 226 | 227 | /* Reset SLEEPDEEP bit of Cortex System Control Register */ 228 | SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP); 229 | } 230 | 231 | /** 232 | * @brief Enters STANDBY mode. 233 | * @param None 234 | * @retval None 235 | */ 236 | void PWR_EnterSTANDBYMode(void) 237 | { 238 | /* Clear Wake-up flag */ 239 | PWR->CR |= PWR_CR_CWUF; 240 | /* Select STANDBY mode */ 241 | PWR->CR |= PWR_CR_PDDS; 242 | /* Set SLEEPDEEP bit of Cortex System Control Register */ 243 | SCB->SCR |= SCB_SCR_SLEEPDEEP; 244 | /* This option is used to ensure that store operations are completed */ 245 | #if defined ( __CC_ARM ) 246 | __force_stores(); 247 | #endif 248 | /* Request Wait For Interrupt */ 249 | __WFI(); 250 | } 251 | 252 | /** 253 | * @brief Checks whether the specified PWR flag is set or not. 254 | * @param PWR_FLAG: specifies the flag to check. 255 | * This parameter can be one of the following values: 256 | * @arg PWR_FLAG_WU: Wake Up flag 257 | * @arg PWR_FLAG_SB: StandBy flag 258 | * @arg PWR_FLAG_PVDO: PVD Output 259 | * @retval The new state of PWR_FLAG (SET or RESET). 260 | */ 261 | FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG) 262 | { 263 | FlagStatus bitstatus = RESET; 264 | /* Check the parameters */ 265 | assert_param(IS_PWR_GET_FLAG(PWR_FLAG)); 266 | 267 | if ((PWR->CSR & PWR_FLAG) != (uint32_t)RESET) 268 | { 269 | bitstatus = SET; 270 | } 271 | else 272 | { 273 | bitstatus = RESET; 274 | } 275 | /* Return the flag status */ 276 | return bitstatus; 277 | } 278 | 279 | /** 280 | * @brief Clears the PWR's pending flags. 281 | * @param PWR_FLAG: specifies the flag to clear. 282 | * This parameter can be one of the following values: 283 | * @arg PWR_FLAG_WU: Wake Up flag 284 | * @arg PWR_FLAG_SB: StandBy flag 285 | * @retval None 286 | */ 287 | void PWR_ClearFlag(uint32_t PWR_FLAG) 288 | { 289 | /* Check the parameters */ 290 | assert_param(IS_PWR_CLEAR_FLAG(PWR_FLAG)); 291 | 292 | PWR->CR |= PWR_FLAG << 2; 293 | } 294 | 295 | /** 296 | * @} 297 | */ 298 | 299 | /** 300 | * @} 301 | */ 302 | 303 | /** 304 | * @} 305 | */ 306 | 307 | /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/ 308 | -------------------------------------------------------------------------------- /stm_lib/src/stm32f10x_usart.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/darksidelemm/RS41FOX/9a4e4137032302171b62b3976e8ceb72193e5ecc/stm_lib/src/stm32f10x_usart.c -------------------------------------------------------------------------------- /syscalls/.readme.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /syscalls/syscalls.c: -------------------------------------------------------------------------------- 1 | /**************************************************************************//***** 2 | * @file stdio.c 3 | * @brief Implementation of newlib syscall 4 | ********************************************************************************/ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #undef errno 12 | extern int errno; 13 | extern int _end; 14 | 15 | /*This function is used for handle heap option*/ 16 | __attribute__ ((used)) 17 | caddr_t _sbrk ( int incr ) 18 | { 19 | static unsigned char *heap = NULL; 20 | unsigned char *prev_heap; 21 | 22 | if (heap == NULL) { 23 | heap = (unsigned char *)&_end; 24 | } 25 | prev_heap = heap; 26 | 27 | heap += incr; 28 | 29 | return (caddr_t) prev_heap; 30 | } 31 | 32 | __attribute__ ((used)) 33 | int link(char *old, char *new) 34 | { 35 | return -1; 36 | } 37 | 38 | __attribute__ ((used)) 39 | int _close(int file) 40 | { 41 | return -1; 42 | } 43 | 44 | __attribute__ ((used)) 45 | int _fstat(int file, struct stat *st) 46 | { 47 | st->st_mode = S_IFCHR; 48 | return 0; 49 | } 50 | 51 | __attribute__ ((used)) 52 | int _isatty(int file) 53 | { 54 | return 1; 55 | } 56 | 57 | __attribute__ ((used)) 58 | int _lseek(int file, int ptr, int dir) 59 | { 60 | return 0; 61 | } 62 | 63 | /*Low layer read(input) function*/ 64 | __attribute__ ((used)) 65 | int _read(int file, char *ptr, int len) 66 | { 67 | 68 | #if 0 69 | //user code example 70 | int i; 71 | (void)file; 72 | 73 | for(i = 0; i < len; i++) 74 | { 75 | // UART_GetChar is user's basic input function 76 | *ptr++ = UART_GetChar(); 77 | } 78 | 79 | #endif 80 | 81 | return len; 82 | } 83 | 84 | 85 | /*Low layer write(output) function*/ 86 | __attribute__ ((used)) 87 | int _write(int file, char *ptr, int len) 88 | { 89 | 90 | #if 0 91 | //user code example 92 | 93 | int i; 94 | (void)file; 95 | 96 | for(i = 0; i < len; i++) 97 | { 98 | // UART_PutChar is user's basic output function 99 | UART_PutChar(*ptr++); 100 | } 101 | #endif 102 | 103 | return len; 104 | } 105 | 106 | __attribute__ ((used)) 107 | void abort(void) 108 | { 109 | /* Abort called */ 110 | while(1); 111 | } 112 | 113 | /* --------------------------------- End Of File ------------------------------ */ 114 | -------------------------------------------------------------------------------- /ublox.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SQ5RWU on 2016-12-27. 3 | // 4 | 5 | #include 6 | #include 7 | #include "ublox.h" 8 | #include "delay.h" 9 | #include "init.h" 10 | 11 | GPSEntry currentGPSData; 12 | volatile uint8_t active = 0; 13 | volatile uint8_t ack_received = 0; 14 | volatile uint8_t nack_received = 0; 15 | 16 | void _sendSerialByte(uint8_t message) { 17 | while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) { 18 | } 19 | USART_SendData(USART1, message); 20 | while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET) { 21 | } 22 | } 23 | 24 | void send_ublox(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t payloadSize) { 25 | uBloxChecksum chksum = ublox_calc_checksum(msgClass, msgId, payload, payloadSize); 26 | 27 | _sendSerialByte(0xB5); 28 | _sendSerialByte(0x62); 29 | _sendSerialByte(msgClass); 30 | _sendSerialByte(msgId); 31 | _sendSerialByte((uint8_t) (payloadSize & 0xff)); 32 | _sendSerialByte((uint8_t) (payloadSize >> 8)); 33 | 34 | uint16_t i; 35 | for (i = 0; i < payloadSize; ++i) { 36 | _sendSerialByte(payload[i]); 37 | } 38 | _sendSerialByte(chksum.ck_a); 39 | _sendSerialByte(chksum.ck_b); 40 | } 41 | 42 | void send_ublox_packet(uBloxPacket * packet){ 43 | send_ublox(packet->header.messageClass, packet->header.messageId, (uint8_t*)&packet->data, packet->header.payloadSize); 44 | } 45 | 46 | uBloxChecksum ublox_calc_checksum(const uint8_t msgClass, const uint8_t msgId, const uint8_t *message, uint16_t size) { 47 | uBloxChecksum ck = {0, 0}; 48 | uint8_t i; 49 | ck.ck_a += msgClass; 50 | ck.ck_b += ck.ck_a; 51 | ck.ck_a += msgId; 52 | ck.ck_b += ck.ck_a; 53 | 54 | ck.ck_a += size & 0xff; 55 | ck.ck_b += ck.ck_a; 56 | ck.ck_a += size >> 8; 57 | ck.ck_b += ck.ck_a; 58 | 59 | 60 | for (i =0;iheader.sc1 = data; 137 | } else if (buffer_pos == 1 && data == 0x62){ 138 | sync = 1; 139 | buffer_pos = 2; 140 | incoming_packet->header.sc2 = data; 141 | } else { 142 | buffer_pos = 0; 143 | } 144 | } else { 145 | ((uint8_t *)incoming_packet)[buffer_pos] = data; 146 | if ((buffer_pos >= sizeof(uBloxHeader)-1) && (buffer_pos-1 == (incoming_packet->header.payloadSize + sizeof(uBloxHeader) + sizeof(uBloxChecksum)))){ 147 | ublox_handle_packet((uBloxPacket *) incoming_packet); 148 | buffer_pos = 0; 149 | sync = 0; 150 | } else { 151 | buffer_pos++; 152 | if (buffer_pos >= sizeof(uBloxPacket) + sizeof(uBloxChecksum)) { 153 | buffer_pos = 0; 154 | sync = 0; 155 | } 156 | } 157 | } 158 | } 159 | 160 | void ublox_handle_packet(uBloxPacket *pkt) { 161 | uBloxChecksum cksum = ublox_calc_checksum(pkt->header.messageClass, pkt->header.messageId, (const uint8_t *) &pkt->data, pkt->header.payloadSize); 162 | uBloxChecksum *checksum = (uBloxChecksum *)(((uint8_t*)&pkt->data) + pkt->header.payloadSize); 163 | if (cksum.ck_a != checksum->ck_a || cksum.ck_b != checksum->ck_b) { 164 | currentGPSData.bad_packets += 1; 165 | } else { 166 | 167 | if (pkt->header.messageClass == 0x01 && pkt->header.messageId == 0x07){ 168 | currentGPSData.ok_packets += 1; 169 | currentGPSData.fix = pkt->data.navpvt.fixType; 170 | currentGPSData.lat_raw = pkt->data.navpvt.lat; 171 | currentGPSData.lon_raw = pkt->data.navpvt.lon; 172 | currentGPSData.alt_raw = pkt->data.navpvt.hMSL; 173 | currentGPSData.hours = pkt->data.navpvt.hour; 174 | currentGPSData.minutes = pkt->data.navpvt.min; 175 | currentGPSData.seconds = pkt->data.navpvt.sec; 176 | currentGPSData.sats_raw = pkt->data.navpvt.numSV; 177 | currentGPSData.speed_raw = pkt->data.navpvt.gSpeed; 178 | 179 | } else if (pkt->header.messageClass == 0x01 && pkt->header.messageId == 0x02){ 180 | currentGPSData.ok_packets += 1; 181 | currentGPSData.lat_raw = pkt->data.navposllh.lat; 182 | currentGPSData.lon_raw = pkt->data.navposllh.lon; 183 | currentGPSData.alt_raw = pkt->data.navposllh.hMSL; 184 | } else if (pkt->header.messageClass == 0x01 && pkt->header.messageId == 0x06){ 185 | currentGPSData.fix = pkt->data.navsol.gpsFix; 186 | currentGPSData.sats_raw = pkt->data.navsol.numSV; 187 | } else if (pkt->header.messageClass == 0x01 && pkt->header.messageId == 0x21){ 188 | currentGPSData.hours = pkt->data.navtimeutc.hour; 189 | currentGPSData.minutes = pkt->data.navtimeutc.min; 190 | currentGPSData.seconds = pkt->data.navtimeutc.sec; 191 | } else if (pkt->header.messageClass == 0x05 && pkt->header.messageId == 0x01){ 192 | ack_received = 1; 193 | } else if (pkt->header.messageClass == 0x05 && pkt->header.messageId == 0x00){ 194 | nack_received = 1; 195 | } 196 | } 197 | 198 | } 199 | uint8_t ublox_wait_for_ack() { 200 | ack_received = 0; 201 | nack_received = 0; 202 | uint8_t timeout = 200; 203 | while(!ack_received && !nack_received){ 204 | _delay_ms(1); 205 | if (!timeout--){ 206 | break; 207 | } 208 | } 209 | 210 | return ack_received; 211 | } 212 | 213 | 214 | void ublox_gps_stop(){ 215 | // Set the GPS into a stopped mode. 216 | uBloxPacket msgcfgrst = {.header = {0xb5, 0x62, .messageClass=0x06, .messageId=0x04, .payloadSize=sizeof(uBloxCFGRSTPayload)}, 217 | .data.cfgrst = { .navBbrMask=0xffff, .resetMode=8, .reserved1 = 0} 218 | }; 219 | do { 220 | send_ublox_packet(&msgcfgrst); 221 | } while (!ublox_wait_for_ack()); 222 | } 223 | 224 | -------------------------------------------------------------------------------- /ublox.h: -------------------------------------------------------------------------------- 1 | // 2 | // Created by SQ5RWU on 2016-12-27. 3 | // 4 | 5 | #ifndef RS41HUP_UBLOX_H 6 | #define RS41HUP_UBLOX_H 7 | #include 8 | 9 | typedef struct { 10 | int32_t lat_raw; 11 | int32_t lon_raw; 12 | int32_t alt_raw; 13 | int32_t speed_raw; 14 | uint8_t sats_raw; 15 | uint8_t seconds; 16 | uint8_t minutes; 17 | uint8_t hours; 18 | uint8_t fix; 19 | uint16_t ok_packets; 20 | uint16_t bad_packets; 21 | } GPSEntry; 22 | 23 | typedef struct __attribute__((packed)){ 24 | uint8_t sc1; // 0xB5 25 | uint8_t sc2; // 0x62 26 | uint8_t messageClass; 27 | uint8_t messageId; 28 | uint16_t payloadSize; 29 | } uBloxHeader; 30 | 31 | typedef struct { 32 | uint8_t ck_a; 33 | uint8_t ck_b; 34 | } uBloxChecksum; 35 | 36 | typedef struct { 37 | uint32_t iTOW; //GPS time of week of the navigation epoch. [- ms] 38 | uint16_t year; //Year (UTC) [- y] 39 | uint8_t month; //Month, range 1..12 (UTC) [- month] 40 | uint8_t day; //Day of month, range 1..31 (UTC) [- d] 41 | uint8_t hour; //Hour of day, range 0..23 (UTC) [- h] 42 | uint8_t min; //Minute of hour, range 0..59 (UTC) [- min] 43 | uint8_t sec; //Seconds of minute, range 0..60 (UTC) [- s] 44 | uint8_t valid; //Validity flags (see graphic below) [- -] 45 | uint32_t tAcc; //Time accuracy estimate (UTC) [- ns] 46 | int32_t nano; //Fraction of second, range -1e9 .. 1e9 (UTC) [- ns] 47 | uint8_t fixType; //GNSSfix Type: [- -] 48 | uint8_t flags; //Fix status flags (see graphic below) [- -] 49 | uint8_t flags2; //Additional flags (see graphic below) [- -] 50 | uint8_t numSV; //Number of satellites used in Nav Solution [- -] 51 | int32_t lon; //Longitude [1e-7 deg] 52 | int32_t lat; //Latitude [1e-7 deg] 53 | int32_t height; //Height above ellipsoid [- mm] 54 | int32_t hMSL; //Height above mean sea level [- mm] 55 | uint32_t hAcc; //Horizontal accuracy estimate [- mm] 56 | uint32_t vAcc; //Vertical accuracy estimate [- mm] 57 | int32_t velN; //NED north velocity [- mm/s] 58 | int32_t velE; //NED east velocity [- mm/s] 59 | int32_t velD; //NED down velocity [- mm/s] 60 | int32_t gSpeed; //Ground Speed (2-D) [- mm/s] 61 | int32_t headMot; //Heading of motion (2-D) [1e-5 deg] 62 | uint32_t sAcc; //Speed accuracy estimate [- mm/s] 63 | uint32_t headAcc; //Heading accuracy estimate (both motion and vehicle) [1e-5 deg] 64 | uint16_t pDOP; //Position DOP [0.01 -] 65 | uint8_t reserved1[6]; //Reserved [- -] 66 | int32_t headVeh; //Heading of vehicle (2-D) [1e-5 deg] 67 | uint8_t reserved2[4]; //Reserved [- -] 68 | } uBloxNAVPVTPayload; 69 | 70 | typedef struct { 71 | uint32_t iTOW; //GPS Millisecond Time of Week [- ms] 72 | int32_t lon; //Longitude [1e-7 deg] 73 | int32_t lat; //Latitude [1e-7 deg] 74 | int32_t height; //Height above Ellipsoid [- mm] 75 | int32_t hMSL; //Height above mean sea level [- mm] 76 | uint32_t hAcc; //Horizontal Accuracy Estimate [- mm] 77 | uint32_t vAcc; //Vertical Accuracy Estimate [- mm] 78 | } uBloxNAVPOSLLHPayload; 79 | 80 | typedef struct { 81 | uint32_t iTOW; //GPS Millisecond Time of Week [- ms] 82 | int32_t fTOW; //Fractional Nanoseconds remainder of rounded ms above, range -500000 .. 500000 [- ns] 83 | int16_t week; //GPS week (GPS time) [- -] 84 | uint8_t gpsFix; //GPSfix Type, range 0..5 0x00 = No Fix 0x01 = Dead Reckoning only 0x02 = 2D-Fix 0x03 = 3D-Fix 0x04 = GPS + dead reckoning combined 0x05 = Time only fix 0x06..0xff: reserved [- -] 85 | uint8_t flags; //Fix Status Flags (see graphic below) [- -] 86 | int32_t ecefX; //ECEF X coordinate [- cm] 87 | int32_t ecefY; //ECEF Y coordinate [- cm] 88 | int32_t ecefZ; //ECEF Z coordinate [- cm] 89 | uint32_t pAcc; //3D Position Accuracy Estimate [- cm] 90 | int32_t ecefVX; //ECEF X velocity [- cm/s] 91 | int32_t ecefVY; //ECEF Y velocity [- cm/s] 92 | int32_t ecefVZ; //ECEF Z velocity [- cm/s] 93 | uint32_t sAcc; //Speed Accuracy Estimate [- cm/s] 94 | uint16_t pDOP; //Position DOP [0.01 -] 95 | uint8_t reserved1; //Reserved [- -] 96 | uint8_t numSV; //Number of SVs used in Nav Solution [- -] 97 | uint32_t reserved2; //Reserved [- -] 98 | 99 | } uBloxNAVSOLPayload; 100 | 101 | typedef struct { 102 | uint32_t iTOW; //GPS Millisecond Time of Week [- ms] 103 | uint32_t tAcc; //Time Accuracy Estimate [- ns] 104 | int32_t nano; //Nanoseconds of second, range -1e9 .. 1e9 (UTC) [- ns] 105 | uint16_t year; //Year, range 1999..2099 (UTC) [- y] 106 | uint8_t month; //Month, range 1..12 (UTC) [- month] 107 | uint8_t day; //Day of Month, range 1..31 (UTC) [- d] 108 | uint8_t hour; //Hour of Day, range 0..23 (UTC) [- h] 109 | uint8_t min; //Minute of Hour, range 0..59 (UTC) [- min] 110 | uint8_t sec; //Seconds of Minute, range 0..59 (UTC) [- s] 111 | uint8_t valid; //Validity Flags (see graphic below) [- -] 112 | 113 | } uBloxNAVTIMEUTCPayload; 114 | 115 | typedef struct { 116 | uint8_t portID; //Port Identifier Number (see Serial [- -] 117 | uint8_t reserved1; //Reserved [- -] 118 | uint16_t txReady; //TX ready PIN configuration [- -] 119 | uint32_t mode; //A bit mask describing the UART mode [- -] 120 | uint32_t baudRate; //Baud rate in bits/second [- Bits/s] 121 | uint16_t inProtoMask; //A mask describing which input protocols are active. [- -] 122 | uint16_t outProtoMask; //A mask describing which output protocols are active. [- -] 123 | uint16_t flags; //Flags bit mask (see graphic below) [- -] 124 | uint8_t reserved2[2]; //Reserved [- -] 125 | 126 | } uBloxCFGPRTPayload; 127 | 128 | typedef struct { 129 | uint8_t clsID; //Message Class [- -] 130 | uint8_t msgID; //Message Identifier [- -] 131 | uint8_t ck_a; 132 | uint8_t ck_b; 133 | } uBloxACKACKayload; 134 | 135 | 136 | typedef struct { 137 | uint8_t msgClass; //Message Class [- -] 138 | uint8_t msgID; //Message Identifier [- -] 139 | uint8_t rate; //Send rate on current Port [- -] 140 | } uBloxCFGMSGPayload; 141 | 142 | 143 | typedef struct { 144 | uint16_t navBbrMask; //BBR Sections to clear. The following Special Sets apply: 145 | // 0x0000 Hotstart 146 | // 0x0001 Warmstart 147 | // 0xFFFF Coldstart [- -] 148 | uint8_t resetMode; //Reset Type 149 | // - 0x00 - Hardware reset (Watchdog) immediately 150 | // - 0x01 - Controlled Software reset 151 | // - 0x02 - Controlled Software reset (GPS only) 152 | // - 0x04 - Hardware reset (Watchdog) after shutdown (>=FW6.0) 153 | // - 0x08 - Controlled GPS stop 154 | // - 0x09 - Controlled GPS start [- -] 155 | // - 0x09 - Controlled GPS start [- -] 156 | uint8_t reserved1; //Reserved [- -] 157 | } uBloxCFGRSTPayload; 158 | 159 | typedef struct { 160 | uint16_t mask; //Parameters Bitmask. Only the masked parameters will be applied. (see graphic below) [- -] 161 | uint8_t dynModel; //Dynamic Platform model: - 0 􀀀 Portable - 2 􀀀 Stationary - 3 􀀀 Pedestrian - 4 􀀀 Automotive - 5 􀀀 Sea - 6 􀀀 Airborne with <1g Acceleration - 7 􀀀 Airborne with <2g Acceleration - 8 􀀀 Airborne with <4g Acceleration [- -] 162 | uint8_t fixMode; //Position Fixing Mode. - 1: 2D only - 2: 3D only - 3: Auto 2D/3D [- -] 163 | int32_t fixedAlt; //Fixed altitude (mean sea level) for 2D fix mode. [0.01 m] 164 | uint32_t fixedAltVar; //Fixed altitude variance for 2D mode. [0.0001 m^2] 165 | int8_t minElev; //Minimum Elevation for a GNSS satellite to be used in NAV [- deg] 166 | uint8_t drLimit; //Maximum time to perform dead reckoning (linear extrapolation) in case of GPS signal loss [- s] 167 | uint16_t pDop; //Position DOP Mask to use [0.1 -] 168 | uint16_t tDop; //Time DOP Mask to use [0.1 -] 169 | uint16_t pAcc; //Position Accuracy Mask [- m] 170 | uint16_t tAcc; //Time Accuracy Mask [- m] 171 | uint8_t staticHoldThresh; //Static hold threshold [- cm/s] 172 | uint8_t dgpsTimeOut; //DGPS timeout, firmware 7 and newer only [- s] 173 | uint32_t reserved2; //Always set to zero [- -] 174 | uint32_t reserved3; //Always set to zero [- -] 175 | uint32_t reserved4; //Always set to zero [- -] 176 | } uBloxCFGNAV5Payload; 177 | 178 | typedef struct { 179 | uint8_t reserved1; //Always set to 8 [- -] 180 | uint8_t lpMode; //Low Power Mode 0: Max. performance mode 1: Power Save Mode (>= FW 6.00 only) 2-3: reserved 4: Eco mode 5-255: reserved [- -] 181 | } uBloxCFGRXMPayload; 182 | 183 | typedef union { 184 | uBloxNAVPVTPayload navpvt; 185 | uBloxCFGPRTPayload cfgprt; 186 | uBloxCFGMSGPayload cfgmsg; 187 | uBloxCFGNAV5Payload cfgnav5; 188 | uBloxNAVPOSLLHPayload navposllh; 189 | uBloxNAVSOLPayload navsol; 190 | uBloxNAVTIMEUTCPayload navtimeutc; 191 | uBloxACKACKayload ackack; 192 | uBloxCFGRSTPayload cfgrst; 193 | uBloxCFGRXMPayload cfgrxm; 194 | } ubloxPacketData; 195 | 196 | typedef struct __attribute__((packed)){ 197 | uBloxHeader header; 198 | ubloxPacketData data; 199 | } uBloxPacket; 200 | 201 | void ublox_init(); 202 | void send_ublox(uint8_t msgClass, uint8_t msgId, uint8_t *payload, uint16_t payloadSize); 203 | void send_ublox_packet(uBloxPacket * packet); 204 | void ublox_get_last_data(GPSEntry * gpsEntry); 205 | uBloxChecksum ublox_calc_checksum(const uint8_t msgClass, const uint8_t msgId, const uint8_t *message, uint16_t size); 206 | void ublox_handle_incoming_byte(uint8_t data); 207 | void ublox_handle_packet(uBloxPacket *pkt); 208 | uint8_t ublox_wait_for_ack(); 209 | void ublox_gps_stop(); 210 | 211 | #endif //RS41HUP_UBLOX_H 212 | -------------------------------------------------------------------------------- /util.c: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | uint16_t string_CRC16_checksum(char *string) { 4 | uint16_t crc = 0xffff; 5 | char i; 6 | while (*(string) != 0) { 7 | crc = crc ^ (*(string++) << 8); 8 | for (i = 0; i < 8; i++) { 9 | if (crc & 0x8000) 10 | crc = (uint16_t) ((crc << 1) ^ 0x1021); 11 | else 12 | crc <<= 1; 13 | } 14 | } 15 | return crc; 16 | } 17 | 18 | uint16_t array_CRC16_checksum(char *string, int len) { 19 | uint16_t crc = 0xffff; 20 | char i; 21 | int ptr = 0; 22 | while (ptr < len) { 23 | ptr++; 24 | crc = crc ^ (*(string++) << 8); 25 | for (i = 0; i < 8; i++) { 26 | if (crc & 0x8000) 27 | crc = (uint16_t) ((crc << 1) ^ 0x1021); 28 | else 29 | crc <<= 1; 30 | } 31 | } 32 | return crc; 33 | } 34 | 35 | void print_hex(char *data, uint8_t length, char *tmp) // prints 8-bit data in hex 36 | { 37 | uint8_t first ; 38 | int j=0; 39 | for (uint8_t i=0; i> 4) | 48; 42 | if (first > 57) tmp[j] = first + (uint8_t)39; 43 | else tmp[j] = first ; 44 | j++; 45 | 46 | first = ((uint8_t)data[i] & 0x0F) | 48; 47 | if (first > 57) tmp[j] = first + (uint8_t)39; 48 | else tmp[j] = first; 49 | j++; 50 | } 51 | tmp[length*2] = '\n'; 52 | tmp[length*2+1] = 0; 53 | // Serial.println(tmp); 54 | } -------------------------------------------------------------------------------- /util.h: -------------------------------------------------------------------------------- 1 | #include 2 | uint16_t string_CRC16_checksum(char *string); 3 | uint16_t array_CRC16_checksum(char *string, int len); 4 | void print_hex(char *data, uint8_t length, char *tmp); --------------------------------------------------------------------------------