Repository: pekkaroi/bldc-drive
Branch: master
Commit: eff75760298f
Files: 138
Total size: 4.0 MB
Directory structure:
gitextract_di5jfrul/
├── .gitignore
├── LICENSE
├── README.md
├── firmware/
│ ├── .cproject
│ ├── .project
│ ├── include/
│ │ └── stm32f10x_conf.h
│ ├── ldscripts/
│ │ ├── libs.ld
│ │ ├── mem.ld
│ │ └── sections.ld
│ ├── src/
│ │ ├── adc.c
│ │ ├── adc.h
│ │ ├── configuration.c
│ │ ├── configuration.h
│ │ ├── eeprom.c
│ │ ├── eeprom.h
│ │ ├── encoder.c
│ │ ├── encoder.h
│ │ ├── hall.c
│ │ ├── hall.h
│ │ ├── input.c
│ │ ├── input.h
│ │ ├── main.c
│ │ ├── pid.c
│ │ ├── pid.h
│ │ ├── pwm.c
│ │ ├── pwm.h
│ │ ├── usart.c
│ │ ├── usart.h
│ │ ├── utils.c
│ │ └── utils.h
│ └── system/
│ ├── include/
│ │ ├── arm/
│ │ │ └── semihosting.h
│ │ ├── cmsis/
│ │ │ ├── README_CMSIS.txt
│ │ │ ├── README_DEVICE.txt
│ │ │ ├── arm_common_tables.h
│ │ │ ├── arm_const_structs.h
│ │ │ ├── arm_math.h
│ │ │ ├── cmsis_device.h
│ │ │ ├── core_cm0.h
│ │ │ ├── core_cm0plus.h
│ │ │ ├── core_cm3.h
│ │ │ ├── core_cm4.h
│ │ │ ├── core_cm4_simd.h
│ │ │ ├── core_cmFunc.h
│ │ │ ├── core_cmInstr.h
│ │ │ ├── core_sc000.h
│ │ │ ├── core_sc300.h
│ │ │ ├── stm32f10x.h
│ │ │ └── system_stm32f10x.h
│ │ ├── cortexm/
│ │ │ └── ExceptionHandlers.h
│ │ ├── diag/
│ │ │ └── Trace.h
│ │ └── stm32f1-stdperiph/
│ │ ├── README_STDPERIPH.txt
│ │ ├── misc.h
│ │ ├── stm32f10x_adc.h
│ │ ├── stm32f10x_bkp.h
│ │ ├── stm32f10x_can.h
│ │ ├── stm32f10x_cec.h
│ │ ├── stm32f10x_crc.h
│ │ ├── stm32f10x_dac.h
│ │ ├── stm32f10x_dbgmcu.h
│ │ ├── stm32f10x_dma.h
│ │ ├── stm32f10x_exti.h
│ │ ├── stm32f10x_flash.h
│ │ ├── stm32f10x_fsmc.h
│ │ ├── stm32f10x_gpio.h
│ │ ├── stm32f10x_i2c.h
│ │ ├── stm32f10x_iwdg.h
│ │ ├── stm32f10x_pwr.h
│ │ ├── stm32f10x_rcc.h
│ │ ├── stm32f10x_rtc.h
│ │ ├── stm32f10x_sdio.h
│ │ ├── stm32f10x_spi.h
│ │ ├── stm32f10x_tim.h
│ │ ├── stm32f10x_usart.h
│ │ └── stm32f10x_wwdg.h
│ └── src/
│ ├── cmsis/
│ │ ├── README_DEVICE.txt
│ │ ├── system_stm32f10x.c
│ │ └── vectors_stm32f10x.c
│ ├── cortexm/
│ │ ├── _initialize_hardware.c
│ │ ├── _reset_hardware.c
│ │ └── exception_handlers.c
│ ├── diag/
│ │ ├── Trace.c
│ │ └── trace_impl.c
│ ├── newlib/
│ │ ├── README.txt
│ │ ├── _cxx.cpp
│ │ ├── _exit.c
│ │ ├── _sbrk.c
│ │ ├── _startup.c
│ │ ├── _syscalls.c
│ │ ├── _write.c
│ │ └── assert.c
│ └── stm32f1-stdperiph/
│ ├── README_STDPERIPH.txt
│ ├── misc.c
│ ├── stm32f10x_adc.c
│ ├── stm32f10x_bkp.c
│ ├── stm32f10x_can.c
│ ├── stm32f10x_cec.c
│ ├── stm32f10x_crc.c
│ ├── stm32f10x_dac.c
│ ├── stm32f10x_dbgmcu.c
│ ├── stm32f10x_dma.c
│ ├── stm32f10x_exti.c
│ ├── stm32f10x_flash.c
│ ├── stm32f10x_fsmc.c
│ ├── stm32f10x_gpio.c
│ ├── stm32f10x_i2c.c
│ ├── stm32f10x_iwdg.c
│ ├── stm32f10x_pwr.c
│ ├── stm32f10x_rcc.c
│ ├── stm32f10x_rtc.c
│ ├── stm32f10x_sdio.c
│ ├── stm32f10x_spi.c
│ ├── stm32f10x_tim.c
│ ├── stm32f10x_usart.c
│ └── stm32f10x_wwdg.c
├── gui/
│ ├── ServoGui.py
│ ├── __init__.py
│ └── servogui.nja
└── hardware/
├── bldc_control_v2/
│ ├── bldc_control_ver2.kicad_pcb
│ ├── bldc_control_ver2.net
│ ├── bldc_control_ver2.pro
│ └── bldc_control_ver2.sch
├── bldc_control_v3/
│ ├── bldc_control_ver3.kicad_pcb
│ ├── bldc_control_ver3.net
│ ├── bldc_control_ver3.pro
│ └── bldc_control_ver3.sch
├── bldc_drive_v2/
│ ├── Alu_casing.kicad_pcb
│ ├── Alu_casing.pro
│ ├── bldc_drive.kicad_pcb
│ ├── bldc_drive.net
│ ├── bldc_drive.pro
│ └── bldc_drive.sch
└── libraries/
├── 6n137.bck
├── 6n137.dcm
├── 6n137.lib
├── INA270.lib
├── custom_7805.dcm
├── custom_7805.lib
└── vias.pretty/
└── Via-0.6mm.kicad_mod
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
# Object files
*.o
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.a
*.la
*.lo
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
.settings/
Debug/
output/
_autosave*
# Eclipse Files
./Debug/
./Release/
.settings
# KiCAD Backup and temp files
*.bak
*-cache.lib
*.kicad_pcb-bak
*.csv
*.xml
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
{description}
Copyright (C) {year} {fullname}
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
{signature of Ty Coon}, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
================================================
FILE: README.md
================================================
# bldc-drive
This is a project developing a simple BLDC servo controller. It is based on an STM32F103 microcontroller.
Some parts, especially the PID control loop is based on development done by user mcm_xyz in cnczone.com forum. Thank you! Check the thread http://www.cnczone.com/forums/open-source-controller-boards/283428-cnc.html
## Disclaimer
This software and hardware is provided "AS IS", WITHOUT ANY WARRANTY. The software is released under GPL v2. Authors accept no liability for any harm or loss resulting from use of this hardware or software.
## Authors & Contributors
* original Software by mcm_xyz from cnczone
* first Version of Hardware&Software in a Git-repo from pekkaroi via https://github.com/pekkaroi
* Schematic-additions and fork by Philipp Hörauf via https://github.com/Virtex7
## Firmware
Firmware is a work-in-progress (and will be for a while :), however following features are included:
* Trapezoidal BLDC commutation using either HALL sensors or quadrature encoder.
* Step+Dir input interface with PID position control loop.
* PWM+Dir input interface in velocity mode.
* USART communitacation for configuration. Configuration settings saved to flash memory.
* TODO: Motor Test Mode to simply activate a Motor with a fixed frequency, no encoder needed
### Update 1st May 2016
Some updates to the firmware.
* ADC current limiting implemented. Appears to work OK
* I created a quick and ugly Python gui for tuning
* Updated the PID loop to have feedfoward coefficients FF1 and FF2 (like LinuxCNC). This means that the PID output can be adjusted by the requested speed and the requested acceleration. This made the PID tuning a lot easier for me at least, I'm able to get a motor to follow the requested position very well also during acceleration and during constant drive.
## Hardware:
First prototype hardware is built and it is working well. However, there are couple of known issues:
* 6n137 optocoupler is not officially supporting 3.3V supply voltage which is used in the board. In reality they seem to work, but the optocoupler should be changed or additional levelshifting circuitry added on next revision. Also, the optocoupler input circuit supports only push-pull-type encoder output. Many encoders seem to have open drain output. :(
* Few connectors in the layout missed solder stop openings. They were bit painfull to solder. :)
* The current amplifier INA27x connection is wrong. The IN+ and IN- should be swapped.
### STATUS QUO:
Second hardware revision with the above findings fixed is published. There are no known issues, two servo drives are succesfully driving my CNC router. Pics and videos to come..
### HARDWARE TODOs:
* verify all part-values into the schematic
================================================
FILE: firmware/.cproject
================================================
================================================
FILE: firmware/.project
================================================
bldc_driveorg.eclipse.cdt.managedbuilder.core.genmakebuilderclean,full,incremental,org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilderfull,incremental,org.eclipse.cdt.core.cnatureorg.eclipse.cdt.managedbuilder.core.managedBuildNatureorg.eclipse.cdt.managedbuilder.core.ScannerConfigNatureorg.eclipse.cdt.core.ccnature
================================================
FILE: firmware/include/stm32f10x_conf.h
================================================
/**
******************************************************************************
* @file Project/STM32F10x_StdPeriph_Template/stm32f10x_conf.h
* @author MCD Application Team
* @version V3.5.0
* @date 08-April-2011
* @brief Library configuration file.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_CONF_H
#define __STM32F10x_CONF_H
/* Includes ------------------------------------------------------------------*/
/* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */
#include "stm32f10x_adc.h"
#include "stm32f10x_bkp.h"
#include "stm32f10x_can.h"
#include "stm32f10x_cec.h"
#include "stm32f10x_crc.h"
#include "stm32f10x_dac.h"
#include "stm32f10x_dbgmcu.h"
#include "stm32f10x_dma.h"
#include "stm32f10x_exti.h"
#include "stm32f10x_flash.h"
#include "stm32f10x_fsmc.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_i2c.h"
#include "stm32f10x_iwdg.h"
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_rtc.h"
#include "stm32f10x_sdio.h"
#include "stm32f10x_spi.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_usart.h"
#include "stm32f10x_wwdg.h"
#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Uncomment the line below to expanse the "assert_param" macro in the
Standard Peripheral Library drivers code */
/* #define USE_FULL_ASSERT 1 */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function which reports
* the name of the source file and the source line number of the call
* that failed. If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0)
#endif /* USE_FULL_ASSERT */
//#define VECT_TAB_SRAM
#endif /* __STM32F10x_CONF_H */
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/ldscripts/libs.ld
================================================
/*
* Placeholder to list other libraries required by the application.
GROUP(
)
*/
================================================
FILE: firmware/ldscripts/mem.ld
================================================
/*
* Memory Spaces Definitions.
*
* Need modifying for a specific board.
* FLASH.ORIGIN: starting address of flash
* FLASH.LENGTH: length of flash
* RAM.ORIGIN: starting address of RAM bank 0
* RAM.LENGTH: length of RAM bank 0
*
* The values below can be addressed in further linker scripts
* using functions like 'ORIGIN(RAM)' or 'LENGTH(RAM)'.
*/
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
CCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 0
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
MEMORY_ARRAY (xrw) : ORIGIN = 0x00000000, LENGTH = 0
}
/*
* For external ram use something like:
RAM (xrw) : ORIGIN = 0x68000000, LENGTH = 20K
*/
================================================
FILE: firmware/ldscripts/sections.ld
================================================
/*
* Default linker script for STM32Fxxx.
*/
/*
* The '__stack' definition is required by crt0, do not remove it.
*/
__stack = ORIGIN(RAM) + LENGTH(RAM);
_estack = __stack; /* STM specific definition */
/*
* Default stack sizes.
* These are used by the startup in order to allocate stacks
* for the different modes.
*/
__Main_Stack_Size = 1024 ;
PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;
__Main_Stack_Limit = __stack - __Main_Stack_Size ;
/*"PROVIDE" allows to easily override these values from an object file or the command line. */
PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ;
/*
* There will be a link error if there is not this amount of
* RAM free at the end.
*/
_Minimum_Stack_Size = 256 ;
/*
* Default heap definitions.
* The heap start immediately after the last statically allocated
* .sbss/.noinit section, and extends up to the main stack limit.
*/
PROVIDE ( _Heap_Begin = _end_noinit ) ;
PROVIDE ( _Heap_Limit = __stack - __Main_Stack_Size ) ;
/*
* The entry point is informative, for debuggers and simulators,
* since the Cortex-M vector points to it anyway.
*/
ENTRY(_start)
/* Sections Definitions */
SECTIONS
{
/*
* For Cortex-M devices, the beginning of the startup code is stored in
* the .isr_vector section, which goes to FLASH
*/
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Interrupt vectors */
KEEP(*(.cfmconfig)) /* Freescale configuration words */
/*
* This section is here for convenience, to store the
* startup code at the beginning of the flash area, hoping that
* this will increase the readability of the listing.
*/
*(.after_vectors .after_vectors.*) /* Startup code and ISR */
. = ALIGN(4);
} >FLASH
.inits :
{
. = ALIGN(4);
/*
* These are the old initialisation sections, intended to contain
* naked code, with the prologue/epilogue added by crti.o/crtn.o
* when linking with startup files. The standalone startup code
* currently does not run these, better use the init arrays below.
*/
KEEP(*(.init))
KEEP(*(.fini))
. = ALIGN(4);
/*
* The preinit code, i.e. an array of pointers to initialisation
* functions to be performed before constructors.
*/
PROVIDE_HIDDEN (__preinit_array_start = .);
/*
* Used to run the SystemInit() before anything else.
*/
KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))
/*
* Used for other platform inits.
*/
KEEP(*(.preinit_array_platform .preinit_array_platform.*))
/*
* The application inits. If you need to enforce some order in
* execution, create new sections, as before.
*/
KEEP(*(.preinit_array .preinit_array.*))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/*
* The init code, i.e. an array of pointers to static constructors.
*/
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/*
* The fini code, i.e. an array of pointers to static destructors.
*/
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
} >FLASH
/*
* For some STRx devices, the beginning of the startup code
* is stored in the .flashtext section, which goes to FLASH.
*/
.flashtext :
{
. = ALIGN(4);
*(.flashtext .flashtext.*) /* Startup code */
. = ALIGN(4);
} >FLASH
/*
* The program code is stored in the .text section,
* which goes to FLASH.
*/
.text :
{
. = ALIGN(4);
*(.text .text.*) /* all remaining code */
*(.rodata .rodata.*) /* read-only data (constants) */
*(vtable) /* C++ virtual tables */
KEEP(*(.eh_frame*))
/*
* Stub sections generated by the linker, to glue together
* ARM and Thumb code. .glue_7 is used for ARM code calling
* Thumb code, and .glue_7t is used for Thumb code calling
* ARM code. Apparently always generated by the linker, for some
* architectures, so better leave them here.
*/
*(.glue_7)
*(.glue_7t)
} >FLASH
/* ARM magic sections */
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
. = ALIGN(4);
_etext = .;
__etext = .;
/*
* This address is used by the startup code to
* initialise the .data section.
*/
_sidata = _etext;
/* MEMORY_ARRAY */
/*
.ROarraySection :
{
*(.ROarraySection .ROarraySection.*)
} >MEMORY_ARRAY
*/
/*
* The initialised data section.
* The program executes knowing that the data is in the RAM
* but the loader puts the initial values in the FLASH (inidata).
* It is one task of the startup to copy the initial values from
* FLASH to RAM.
*/
.data : AT ( _sidata )
{
. = ALIGN(4);
/* This is used by the startup code to initialise the .data section */
_sdata = . ; /* STM specific definition */
__data_start__ = . ;
*(.data_begin .data_begin.*)
*(.data .data.*)
*(.data_end .data_end.*)
. = ALIGN(4);
/* This is used by the startup code to initialise the .data section */
_edata = . ; /* STM specific definition */
__data_end__ = . ;
} >RAM
/*
* The uninitialised data section. NOLOAD is used to avoid
* the "section `.bss' type changed to PROGBITS" warning
*/
.bss (NOLOAD) :
{
. = ALIGN(4);
__bss_start__ = .; /* standard newlib definition */
_sbss = .; /* STM specific definition */
*(.bss_begin .bss_begin.*)
*(.bss .bss.*)
*(COMMON)
*(.bss_end .bss_end.*)
. = ALIGN(4);
__bss_end__ = .; /* standard newlib definition */
_ebss = . ; /* STM specific definition */
} >RAM
.noinit (NOLOAD) :
{
. = ALIGN(4);
_noinit = .;
*(.noinit .noinit.*)
. = ALIGN(4) ;
_end_noinit = .;
} > RAM
/* Mandatory to be word aligned, _sbrk assumes this */
PROVIDE ( end = _end_noinit ); /* was _ebss */
PROVIDE ( _end = _end_noinit );
PROVIDE ( __end = _end_noinit );
PROVIDE ( __end__ = _end_noinit );
/*
* Used for validation only, do not allocate anything here!
*
* This is just to check that there is enough RAM left for the Main
* stack. It should generate an error if it's full.
*/
._check_stack :
{
. = ALIGN(4);
. = . + _Minimum_Stack_Size ;
. = ALIGN(4);
} >RAM
.bss_CCMRAM : ALIGN(4)
{
*(.bss.CCMRAM .bss.CCMRAM.*)
} > CCMRAM
/*
* The FLASH Bank1.
* The C or assembly source must explicitly place the code
* or data there using the "section" attribute.
*/
.b1text :
{
*(.b1text) /* remaining code */
*(.b1rodata) /* read-only data (constants) */
*(.b1rodata.*)
} >FLASHB1
/*
* The EXTMEM.
* The C or assembly source must explicitly place the code or data there
* using the "section" attribute.
*/
/* EXTMEM Bank0 */
.eb0text :
{
*(.eb0text) /* remaining code */
*(.eb0rodata) /* read-only data (constants) */
*(.eb0rodata.*)
} >EXTMEMB0
/* EXTMEM Bank1 */
.eb1text :
{
*(.eb1text) /* remaining code */
*(.eb1rodata) /* read-only data (constants) */
*(.eb1rodata.*)
} >EXTMEMB1
/* EXTMEM Bank2 */
.eb2text :
{
*(.eb2text) /* remaining code */
*(.eb2rodata) /* read-only data (constants) */
*(.eb2rodata.*)
} >EXTMEMB2
/* EXTMEM Bank0 */
.eb3text :
{
*(.eb3text) /* remaining code */
*(.eb3rodata) /* read-only data (constants) */
*(.eb3rodata.*)
} >EXTMEMB3
/* After that there are only debugging sections. */
/* This can remove the debugging information from the standard libraries */
/*
DISCARD :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
*/
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/*
* DWARF debug sections.
* Symbols in the DWARF debugging sections are relative to the beginning
* of the section so we begin them at 0.
*/
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}
================================================
FILE: firmware/src/adc.c
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include
#include
#include
#include
//#include <>
#include "adc.h"
#include "pwm.h"
volatile uint16_t ADC_value;
volatile uint16_t max_duty;
void initADC()
{
max_duty=MAX_DUTY;
GPIO_InitTypeDef GPIO_InitStructure;
//--Enable ADC1 and GPIOA--
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; //PA4 = bus measurement
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
GPIO_Init(GPIOA, &GPIO_InitStructure);
ADC_InitTypeDef ADC_InitStructure;
//ADC1 configuration
ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;//!
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
//load structure values to control and status registers
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 1, ADC_SampleTime_41Cycles5);
//Enable ADC1
ADC_Cmd(ADC1, ENABLE);
//enable DMA for ADC
ADC_DMACmd(ADC1, ENABLE);
//Enable ADC1 reset calibration register
ADC_ResetCalibration(ADC1);
//Check the end of ADC1 reset calibration register
while(ADC_GetResetCalibrationStatus(ADC1));
//Start ADC1 calibration
ADC_StartCalibration(ADC1);
//Check the end of ADC1 calibration
while(ADC_GetCalibrationStatus(ADC1));
//enable DMA1 clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
//create DMA structure
DMA_InitTypeDef DMA_InitStructure;
//reset DMA1 channe1 to default values;
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_BufferSize = 1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)&ADC_value;
//send values to DMA registers
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
// Enable DMA1 Channel Transfer Complete interrupt
DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE); //Enable the DMA1 - Channel1
//Enable DMA1 channel IRQ Channel */
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void ADC1_2_IRQHandler(void) {
if (ADC_GetITStatus(ADC1, ADC_IT_EOC) != RESET)
{
ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
}
}
void DMA1_Channel1_IRQHandler(void) {
if(DMA_GetITStatus(DMA1_IT_TC1)) {
DMA_ClearITPendingBit(DMA1_IT_GL1);
DMA_Cmd(DMA1_Channel1, ENABLE);
if(ADC_value>s.max_current && max_duty>1)
{
max_duty -= 2;
return;
}
if(ADC_value<=s.max_current && max_duty
#include
#define EADDR_IS_INITIALIZED 0x0001
#define EADDR_CONFIG_START 0x0002
void writeConfig()
{
FLASH_Unlock();
uint16_t i;
int16_t *ptr = (int16_t *)&s;
for(i=0; i
/*
* functionality from sinusoid_drive branch has been merged to master brach 13.2.2017. define SINUSOID_DRIVE to
* enable sinusoid commutation, comment it out to define trapezoidal commutation.
*
*/
#define SINUSOID_DRIVE 1
//PID timer period. Counter runs at 1MHz, so f_pid = 1e6/period. 250=4kHz, 125=8Khz, 63=16kHz..
#define PID_TIM_PERIOD 40
//BLDC_CHOPPER_PERIOD defines the PWM clock frequency. Timer runs at 72MHz (Fcpu), so Fpwm = 72e6/period
//4000 = 18kHz
//2000 = 36kHz
#define BLDC_CHOPPER_PERIOD 2000
#ifndef SINUSOID_DRIVE
#define MAX_DUTY BLDC_CHOPPER_PERIOD-50 //100% duty not allowed to allow recharge of high side gate drivers
#else
#define ZERO_DUTY BLDC_CHOPPER_PERIOD/2
#define MAX_DUTY BLDC_CHOPPER_PERIOD/2-50 //100% duty not allowed to allow recharge of high side gate drivers
#endif
#define BLDC_NOL 7//Non-OverLapping, number of clock cycles
#define BLDC_DELAY 100 //Commutation delay. 1= no delay, 2000=7ms.
#define inputMethod_stepDir 1
#define inputMethod_pwmVelocity 2
#define commutationMethod_HALL 1
#define commutationMethod_Encoder 2
#define is_ena_inverted (s.invert_dirstepena>>0)&1
#define is_step_inverted (s.invert_dirstepena>>1)&1
#define is_dir_inverted (s.invert_dirstepena>>2)&1
typedef struct {
volatile uint16_t inputMethod;
volatile uint16_t commutationMethod;
volatile uint16_t encoder_PPR;
volatile uint16_t encoder_poles;
volatile uint16_t max_error;
volatile uint16_t invert_dirstepena;
volatile int16_t encoder_counts_per_step;
volatile uint16_t max_current;
volatile int16_t pid_Kp;
volatile int16_t pid_Ki;
volatile int16_t pid_Kd;
volatile int16_t pid_FF1;
volatile int16_t pid_FF2;
volatile uint16_t pid_deadband;
volatile int16_t commutation_offset;
volatile uint16_t usart_baud; //baud divided by 100 to fit to 16 bits! for example 115200 => 1152
} servoConfig;
void getConfig();
void setConfig(char* param, int16_t value);
void writeConfig();
void printConfiguration();
#endif /* CONFIGURATION_H_ */
================================================
FILE: firmware/src/eeprom.c
================================================
/**
******************************************************************************
* @file EEPROM_Emulation/src/eeprom.c
* @author MCD Application Team
* @version V3.1.0
* @date 07/27/2009
* @brief This file provides all the EEPROM emulation firmware functions.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
*/
/** @addtogroup EEPROM_Emulation
* @{
*/
/* Includes ------------------------------------------------------------------*/
#include "eeprom.h"
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Global variable used to store variable value in read sequence */
uint16_t DataVar = 0;
/* Virtual address defined by the user: 0xFFFF value is prohibited */
uint16_t VirtAddVarTab[17] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17};
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
static FLASH_Status EE_Format(void);
static uint16_t EE_FindValidPage(uint8_t Operation);
static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data);
static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data);
/**
* @brief Restore the pages to a known good state in case of page's status
* corruption after a power loss.
* @param None.
* @retval - Flash error code: on write Flash error
* - FLASH_COMPLETE: on success
*/
uint16_t EE_Init(void)
{
uint16_t PageStatus0 = 6, PageStatus1 = 6;
uint16_t VarIdx = 0;
uint16_t EepromStatus = 0, ReadStatus = 0;
int16_t x = -1;
uint16_t FlashStatus;
/* Get Page0 status */
PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
/* Get Page1 status */
PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
/* Check for invalid header states and repair if necessary */
switch (PageStatus0)
{
case ERASED:
if (PageStatus1 == VALID_PAGE) /* Page0 erased, Page1 valid */
{
/* Erase Page0 */
FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
else if (PageStatus1 == RECEIVE_DATA) /* Page0 erased, Page1 receive */
{
/* Erase Page0 */
FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Mark Page1 as valid */
FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
else /* First EEPROM access (Page0&1 are erased) or invalid state -> format EEPROM */
{
/* Erase both Page0 and Page1 and set Page0 as valid page */
FlashStatus = EE_Format();
/* If erase/program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
break;
case RECEIVE_DATA:
if (PageStatus1 == VALID_PAGE) /* Page0 receive, Page1 valid */
{
/* Transfer data from Page1 to Page0 */
for (VarIdx = 0; VarIdx < NumbOfVar; VarIdx++)
{
if (( *(__IO uint16_t*)(PAGE0_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
{
x = VarIdx;
}
if (VarIdx != x)
{
/* Read the last variables' updates */
ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
/* In case variable corresponding to the virtual address was found */
if (ReadStatus != 0x1)
{
/* Transfer the variable to the Page0 */
EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
/* If program operation was failed, a Flash error code is returned */
if (EepromStatus != FLASH_COMPLETE)
{
return EepromStatus;
}
}
}
}
/* Mark Page0 as valid */
FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Erase Page1 */
FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
else if (PageStatus1 == ERASED) /* Page0 receive, Page1 erased */
{
/* Erase Page1 */
FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Mark Page0 as valid */
FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
else /* Invalid state -> format eeprom */
{
/* Erase both Page0 and Page1 and set Page0 as valid page */
FlashStatus = EE_Format();
/* If erase/program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
break;
case VALID_PAGE:
if (PageStatus1 == VALID_PAGE) /* Invalid state -> format eeprom */
{
/* Erase both Page0 and Page1 and set Page0 as valid page */
FlashStatus = EE_Format();
/* If erase/program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
else if (PageStatus1 == ERASED) /* Page0 valid, Page1 erased */
{
/* Erase Page1 */
FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
else /* Page0 valid, Page1 receive */
{
/* Transfer data from Page0 to Page1 */
for (VarIdx = 0; VarIdx < NumbOfVar; VarIdx++)
{
if ((*(__IO uint16_t*)(PAGE1_BASE_ADDRESS + 6)) == VirtAddVarTab[VarIdx])
{
x = VarIdx;
}
if (VarIdx != x)
{
/* Read the last variables' updates */
ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
/* In case variable corresponding to the virtual address was found */
if (ReadStatus != 0x1)
{
/* Transfer the variable to the Page1 */
EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
/* If program operation was failed, a Flash error code is returned */
if (EepromStatus != FLASH_COMPLETE)
{
return EepromStatus;
}
}
}
}
/* Mark Page1 as valid */
FlashStatus = FLASH_ProgramHalfWord(PAGE1_BASE_ADDRESS, VALID_PAGE);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Erase Page0 */
FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
}
break;
default: /* Any other state -> format eeprom */
/* Erase both Page0 and Page1 and set Page0 as valid page */
FlashStatus = EE_Format();
/* If erase/program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
break;
}
return FLASH_COMPLETE;
}
/**
* @brief Returns the last stored variable data, if found, which correspond to
* the passed virtual address
* @param VirtAddress: Variable virtual address
* @param Data: Global variable contains the read variable value
* @retval Success or error status:
* - 0: if variable was found
* - 1: if the variable was not found
* - NO_VALID_PAGE: if no valid page was found.
*/
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
{
uint16_t ValidPage = PAGE0;
uint16_t AddressValue = 0x5555, ReadStatus = 1;
uint32_t Address = 0x08010000, PageStartAddress = 0x08010000;
/* Get active Page for read operation */
ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
/* Check if there is no valid page */
if (ValidPage == NO_VALID_PAGE)
{
return NO_VALID_PAGE;
}
/* Get the valid Page start Address */
PageStartAddress = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE));
/* Get the valid Page end Address */
Address = (uint32_t)((EEPROM_START_ADDRESS - 2) + (uint32_t)((1 + ValidPage) * PAGE_SIZE));
/* Check each active page address starting from end */
while (Address > (PageStartAddress + 2))
{
/* Get the current location content to be compared with virtual address */
AddressValue = (*(__IO uint16_t*)Address);
/* Compare the read address with the virtual address */
if (AddressValue == VirtAddress)
{
/* Get content of Address-2 which is variable value */
*Data = (*(__IO uint16_t*)(Address - 2));
/* In case variable value is read, reset ReadStatus flag */
ReadStatus = 0;
break;
}
else
{
/* Next address location */
Address = Address - 4;
}
}
/* Return ReadStatus value: (0: variable exist, 1: variable doesn't exist) */
return ReadStatus;
}
/**
* @brief Writes/upadtes variable data in EEPROM.
* @param VirtAddress: Variable virtual address
* @param Data: 16 bit data to be written
* @retval Success or error status:
* - FLASH_COMPLETE: on success
* - PAGE_FULL: if valid page is full
* - NO_VALID_PAGE: if no valid page was found
* - Flash error code: on write Flash error
*/
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data)
{
uint16_t Status = 0;
/* Write the variable virtual address and value in the EEPROM */
Status = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
/* In case the EEPROM active page is full */
if (Status == PAGE_FULL)
{
/* Perform Page transfer */
Status = EE_PageTransfer(VirtAddress, Data);
}
/* Return last operation status */
return Status;
}
/**
* @brief Erases PAGE0 and PAGE1 and writes VALID_PAGE header to PAGE0
* @param None
* @retval Status of the last operation (Flash write or erase) done during
* EEPROM formating
*/
static FLASH_Status EE_Format(void)
{
FLASH_Status FlashStatus = FLASH_COMPLETE;
/* Erase Page0 */
FlashStatus = FLASH_ErasePage(PAGE0_BASE_ADDRESS);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Set Page0 as valid page: Write VALID_PAGE at Page0 base address */
FlashStatus = FLASH_ProgramHalfWord(PAGE0_BASE_ADDRESS, VALID_PAGE);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Erase Page1 */
FlashStatus = FLASH_ErasePage(PAGE1_BASE_ADDRESS);
/* Return Page1 erase operation status */
return FlashStatus;
}
/**
* @brief Find valid Page for write or read operation
* @param Operation: operation to achieve on the valid page.
* This parameter can be one of the following values:
* @arg READ_FROM_VALID_PAGE: read operation from valid page
* @arg WRITE_IN_VALID_PAGE: write operation from valid page
* @retval Valid page number (PAGE0 or PAGE1) or NO_VALID_PAGE in case
* of no valid page was found
*/
static uint16_t EE_FindValidPage(uint8_t Operation)
{
uint16_t PageStatus0 = 6, PageStatus1 = 6;
/* Get Page0 actual status */
PageStatus0 = (*(__IO uint16_t*)PAGE0_BASE_ADDRESS);
/* Get Page1 actual status */
PageStatus1 = (*(__IO uint16_t*)PAGE1_BASE_ADDRESS);
/* Write or read operation */
switch (Operation)
{
case WRITE_IN_VALID_PAGE: /* ---- Write operation ---- */
if (PageStatus1 == VALID_PAGE)
{
/* Page0 receiving data */
if (PageStatus0 == RECEIVE_DATA)
{
return PAGE0; /* Page0 valid */
}
else
{
return PAGE1; /* Page1 valid */
}
}
else if (PageStatus0 == VALID_PAGE)
{
/* Page1 receiving data */
if (PageStatus1 == RECEIVE_DATA)
{
return PAGE1; /* Page1 valid */
}
else
{
return PAGE0; /* Page0 valid */
}
}
else
{
return NO_VALID_PAGE; /* No valid Page */
}
case READ_FROM_VALID_PAGE: /* ---- Read operation ---- */
if (PageStatus0 == VALID_PAGE)
{
return PAGE0; /* Page0 valid */
}
else if (PageStatus1 == VALID_PAGE)
{
return PAGE1; /* Page1 valid */
}
else
{
return NO_VALID_PAGE ; /* No valid Page */
}
default:
return PAGE0; /* Page0 valid */
}
}
/**
* @brief Verify if active page is full and Writes variable in EEPROM.
* @param VirtAddress: 16 bit virtual address of the variable
* @param Data: 16 bit data to be written as variable value
* @retval Success or error status:
* - FLASH_COMPLETE: on success
* - PAGE_FULL: if valid page is full
* - NO_VALID_PAGE: if no valid page was found
* - Flash error code: on write Flash error
*/
static uint16_t EE_VerifyPageFullWriteVariable(uint16_t VirtAddress, uint16_t Data)
{
FLASH_Status FlashStatus = FLASH_COMPLETE;
uint16_t ValidPage = PAGE0;
uint32_t Address = 0x08010000, PageEndAddress = 0x080107FF;
/* Get valid Page for write operation */
ValidPage = EE_FindValidPage(WRITE_IN_VALID_PAGE);
/* Check if there is no valid page */
if (ValidPage == NO_VALID_PAGE)
{
return NO_VALID_PAGE;
}
/* Get the valid Page start Address */
Address = (uint32_t)(EEPROM_START_ADDRESS + (uint32_t)(ValidPage * PAGE_SIZE));
/* Get the valid Page end Address */
PageEndAddress = (uint32_t)((EEPROM_START_ADDRESS - 2) + (uint32_t)((1 + ValidPage) * PAGE_SIZE));
/* Check each active page address starting from begining */
while (Address < PageEndAddress)
{
/* Verify if Address and Address+2 contents are 0xFFFFFFFF */
if ((*(__IO uint32_t*)Address) == 0xFFFFFFFF)
{
/* Set variable data */
FlashStatus = FLASH_ProgramHalfWord(Address, Data);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Set variable virtual address */
FlashStatus = FLASH_ProgramHalfWord(Address + 2, VirtAddress);
/* Return program operation status */
return FlashStatus;
}
else
{
/* Next address location */
Address = Address + 4;
}
}
/* Return PAGE_FULL in case the valid page is full */
return PAGE_FULL;
}
/**
* @brief Transfers last updated variables data from the full Page to
* an empty one.
* @param VirtAddress: 16 bit virtual address of the variable
* @param Data: 16 bit data to be written as variable value
* @retval Success or error status:
* - FLASH_COMPLETE: on success
* - PAGE_FULL: if valid page is full
* - NO_VALID_PAGE: if no valid page was found
* - Flash error code: on write Flash error
*/
static uint16_t EE_PageTransfer(uint16_t VirtAddress, uint16_t Data)
{
FLASH_Status FlashStatus = FLASH_COMPLETE;
uint32_t NewPageAddress = 0x080103FF, OldPageAddress = 0x08010000;
uint16_t ValidPage = PAGE0, VarIdx = 0;
uint16_t EepromStatus = 0, ReadStatus = 0;
/* Get active Page for read operation */
ValidPage = EE_FindValidPage(READ_FROM_VALID_PAGE);
if (ValidPage == PAGE1) /* Page1 valid */
{
/* New page address where variable will be moved to */
NewPageAddress = PAGE0_BASE_ADDRESS;
/* Old page address where variable will be taken from */
OldPageAddress = PAGE1_BASE_ADDRESS;
}
else if (ValidPage == PAGE0) /* Page0 valid */
{
/* New page address where variable will be moved to */
NewPageAddress = PAGE1_BASE_ADDRESS;
/* Old page address where variable will be taken from */
OldPageAddress = PAGE0_BASE_ADDRESS;
}
else
{
return NO_VALID_PAGE; /* No valid Page */
}
/* Set the new Page status to RECEIVE_DATA status */
FlashStatus = FLASH_ProgramHalfWord(NewPageAddress, RECEIVE_DATA);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Write the variable passed as parameter in the new active page */
EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddress, Data);
/* If program operation was failed, a Flash error code is returned */
if (EepromStatus != FLASH_COMPLETE)
{
return EepromStatus;
}
/* Transfer process: transfer variables from old to the new active page */
for (VarIdx = 0; VarIdx < NumbOfVar; VarIdx++)
{
if (VirtAddVarTab[VarIdx] != VirtAddress) /* Check each variable except the one passed as parameter */
{
/* Read the other last variable updates */
ReadStatus = EE_ReadVariable(VirtAddVarTab[VarIdx], &DataVar);
/* In case variable corresponding to the virtual address was found */
if (ReadStatus != 0x1)
{
/* Transfer the variable to the new active page */
EepromStatus = EE_VerifyPageFullWriteVariable(VirtAddVarTab[VarIdx], DataVar);
/* If program operation was failed, a Flash error code is returned */
if (EepromStatus != FLASH_COMPLETE)
{
return EepromStatus;
}
}
}
}
/* Erase the old Page: Set old Page status to ERASED status */
FlashStatus = FLASH_ErasePage(OldPageAddress);
/* If erase operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Set new Page status to VALID_PAGE status */
FlashStatus = FLASH_ProgramHalfWord(NewPageAddress, VALID_PAGE);
/* If program operation was failed, a Flash error code is returned */
if (FlashStatus != FLASH_COMPLETE)
{
return FlashStatus;
}
/* Return last operation flash status */
return FlashStatus;
}
/**
* @}
*/
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/src/eeprom.h
================================================
/**
******************************************************************************
* @file EEPROM_Emulation/inc/eeprom.h
* @author MCD Application Team
* @version V3.1.0
* @date 07/27/2009
* @brief This file contains all the functions prototypes for the EEPROM
* emulation firmware library.
******************************************************************************
* @copy
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __EEPROM_H
#define __EEPROM_H
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/* Exported constants --------------------------------------------------------*/
/* Define the STM32F10Xxx Flash page size depending on the used STM32 device */
#if defined (STM32F10X_LD) || defined (STM32F10X_MD)
#define PAGE_SIZE (uint16_t)0x400 /* Page size = 1KByte */
#elif defined (STM32F10X_HD) || defined (STM32F10X_CL)
#define PAGE_SIZE (uint16_t)0x800 /* Page size = 2KByte */
#endif
/* EEPROM start address in Flash */
#define EEPROM_START_ADDRESS ((uint32_t)0x0800F800) /* EEPROM emulation start address:
after 64KByte of used Flash memory */
/* Pages 0 and 1 base and end addresses */
#define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x000))
#define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
#define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + PAGE_SIZE))
#define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))
/* Used Flash pages for EEPROM emulation */
#define PAGE0 ((uint16_t)0x0000)
#define PAGE1 ((uint16_t)0x0001)
/* No valid page define */
#define NO_VALID_PAGE ((uint16_t)0x00AB)
/* Page status definitions */
#define ERASED ((uint16_t)0xFFFF) /* PAGE is empty */
#define RECEIVE_DATA ((uint16_t)0xEEEE) /* PAGE is marked to receive data */
#define VALID_PAGE ((uint16_t)0x0000) /* PAGE containing valid data */
/* Valid pages in read and write defines */
#define READ_FROM_VALID_PAGE ((uint8_t)0x00)
#define WRITE_IN_VALID_PAGE ((uint8_t)0x01)
/* Page full define */
#define PAGE_FULL ((uint8_t)0x80)
/* Variables' number */
#define NumbOfVar ((uint8_t)0x03)
/* Exported types ------------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
/* Exported functions ------------------------------------------------------- */
uint16_t EE_Init(void);
uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data);
uint16_t EE_WriteVariable(uint16_t VirtAddress, uint16_t Data);
#endif /* __EEPROM_H */
/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/src/encoder.c
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include
#include
#include "encoder.h"
#include "usart.h"
#include "input.h"
#include "pwm.h"
#include "hall.h"
#include "utils.h"
#include "adc.h"
#include "math.h"
volatile int32_t encoder_count;
uint16_t encoder_shaft_pos; //this is the shaft position as encoder counts
uint16_t encoder_commutation_pos; //this is shaft position from the beginning of current commuatiton sequence.
#ifndef SINUSOID_DRIVE
uint8_t encoder_commutation_table[4096]; //20 poles max //8096 PPR max at the moment.
#else
int16_t sine_table[4096]; //the required length of sine_table is encoder_ppr/number_of_poles, so this allows quite high ppr encoder..
uint16_t commutation_length; //how many encoder steps there are per commutation circle (i.e encoder_ppr/motor_poles)
#endif
volatile uint16_t encoder_lastCount;
//uint16_t findNextEncoderCommutationCNT(int8_t dir);
void buildCommutationTable()
{
uint16_t i;
#ifndef SINUSOID_DRIVE
for(i=0;iCCR1=i;
TIM1->CCR2=i;
TIM1->CCR3=i;
delay_ms(1);
}
delay_ms(10);
TIM_SetCounter(ENCODER_TIM,0);
encoder_count=0;
encoder_lastCount=0;
encoder_shaft_pos=0;
delay_ms(1);
TIM1->CCR1=0;
TIM1->CCR2=0;
TIM1->CCR3=0;
}
#else
void forcedInitialization()
{
//apply positive voltage (PWM) to phase B and negative to phase C. (Commutation table starts from that position)
if(motor_running)
return;
//TIM_SelectOCxM(TIM1, TIM_Channel_1, TIM_ForcedAction_InActive);
TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Disable);
TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Disable);
TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_OCMode_PWM1);
TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Enable);
TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Enable);
TIM_SelectOCxM(TIM1, TIM_Channel_2, TIM_ForcedAction_Active);
TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Enable);
uint16_t i;
for(i=2000;i<4000;i++)
{
//increase duty until ADC kicks in
if(i>max_duty)
{
TIM1->CCR1=max_duty;
TIM1->CCR2=max_duty;
TIM1->CCR3=max_duty;
}
else
{
TIM1->CCR1=i;
TIM1->CCR2=i;
TIM1->CCR3=i;
}
delay_ms(1);
}
delay_ms(100);
TIM_SetCounter(ENCODER_TIM,0);
encoder_count=0;
encoder_lastCount=0;
encoder_shaft_pos=0;
delay_ms(1);
pwm_motorStop();
}
#endif
void initEncoder()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
if( ENCODER_TIM==TIM2)
{
#ifndef ENCODER_TIM2_REMAP
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
#else
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
#endif
} else
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
TIM_DeInit(ENCODER_TIM);
TIM_TimeBaseInitTypeDef timerInitStructure;
TIM_TimeBaseStructInit(&timerInitStructure);
timerInitStructure.TIM_Prescaler = 0;
timerInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
timerInitStructure.TIM_Period = 0xFFFF;
timerInitStructure.TIM_ClockDivision = 0;
timerInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(ENCODER_TIM, &timerInitStructure);
TIM_EncoderInterfaceConfig (ENCODER_TIM, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising,
TIM_ICPolarity_Rising);
TIM_Cmd(ENCODER_TIM, ENABLE);
if(s.commutationMethod == commutationMethod_Encoder)
{
buildCommutationTable();
forcedInitialization();
}
if(s.commutationMethod == commutationMethod_HALL)
{
encoder_count=0;
encoder_lastCount=0;
encoder_shaft_pos=0;
}
}
void getEncoderCount()
{
uint16_t now = ENCODER_TIM->CNT;
int16_t delta = (int16_t)(now - encoder_lastCount);
encoder_lastCount = now;
encoder_count += delta;
//encoder_full_rounds = encoder_count / s.encoder_PPR;
int16_t shaft_pos_tmp = (encoder_count+ s.commutation_offset ) % s.encoder_PPR;
if(shaft_pos_tmp < 0)
encoder_shaft_pos = s.encoder_PPR + shaft_pos_tmp;
else
encoder_shaft_pos = shaft_pos_tmp;
#ifdef SINUSOID_DRIVE
encoder_commutation_pos = encoder_shaft_pos % commutation_length;
#endif
}
#ifdef SINUSOID_DRIVE
uint16_t getCommutationPos(uint8_t phase)
{
//if driving forward, the commutation must lead the actual position by 90 degrees
//if driving backward, the commutation must lag the actual position by 90 degrees
int32_t tmp;
if(dir)
{
tmp = (encoder_commutation_pos - commutation_length/4 + commutation_length*phase/3);
if (tmp<0)
{
tmp+=commutation_length;
}
return (uint16_t)(tmp % commutation_length);
}
else
{
tmp= (encoder_commutation_pos + commutation_length/4 + commutation_length*phase/3);
if (tmp<0)
{
tmp+=commutation_length;
}
return (uint16_t)(tmp % commutation_length);
}
}
#endif
================================================
FILE: firmware/src/encoder.h
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef ENCODER_H_
#define ENCODER_H_
#include "configuration.h"
#define ENCODER_TIM TIM2
//#define ENCODER_TIM2_REMAP //with this TIM2 connected to PA15 and PB3
void initEncoder();
void getEncoderCount();
uint16_t findCurrentEncoderCommutationPos();
uint16_t findNextEncoderCommutationPos(int8_t dir);
extern volatile servoConfig s;
extern volatile int32_t encoder_count;
extern uint16_t encoder_shaft_pos; //this is the shaft position as encoder counts
extern uint16_t encoder_commutation_pos; //this is shaft position from the beginning of current commuatiton sequence.
#ifndef SINUSOID_DRIVE
extern uint8_t encoder_commutation_table[4096]; //20 poles max //8096 PPR max at the moment.
#else
#define SINE_TABLE_MAX 32767
extern int16_t sine_table[4096]; //20 poles max //8096 PPR max at the moment.
#endif
#endif /* ENCODER_H_ */
================================================
FILE: firmware/src/hall.c
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include
#include
#include "hall.h"
#include "pwm.h"
volatile uint16_t lasthallpos;
volatile uint16_t hallpos;
void initHALL()
{
//Hall sensor is connected to TIM4
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOB, &GPIO_InitStructure);
lasthallpos = ((GPIO_ReadInputData(GPIOB)>>6) & 0x0007);
hallpos = ((GPIO_ReadInputData(GPIOB)>>6) & 0x0007);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler = 126;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_SelectHallSensor(TIM4, ENABLE);
TIM_SelectInputTrigger(TIM4, TIM_TS_TI1F_ED);
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
// listen to T1, the HallSensorEvent
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_TRC;
// Div:1, every edge
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
// input noise filter (reference manual page 322)
TIM_ICInitStructure.TIM_ICFilter = 0xF;
TIM_ICInit(TIM4, &TIM_ICInitStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = BLDC_DELAY; // 1 is no delay; 2000 = 7ms
TIM_OC2Init(TIM4, &TIM_OCInitStructure);
// clear interrupt flag
TIM_ClearFlag(TIM4, TIM_FLAG_CC2);
TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_OC2Ref);
TIM_ITConfig(TIM4, TIM_IT_CC1 | TIM_IT_CC2, ENABLE);
TIM_Cmd(TIM4, ENABLE);
// we use preemption interrupts here, BLDC Bridge switching and
// Hall has highest priority
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM4_IRQHandler(void) {
if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1);
// calculate motor speed or else with CCR1 values
}
else if (TIM_GetITStatus(TIM4, TIM_IT_CC2) != RESET)
{
#ifndef SINUSOID_DRIVE
TIM_ClearITPendingBit(TIM4, TIM_IT_CC2);
uint16_t newhallpos = ((GPIO_ReadInputData(GPIOB)>>6) & 0x0007);
if (newhallpos == hallpos) return;
hallpos = newhallpos;
pwm_Commute(hallpos);
} else {
;
#endif
}
}
================================================
FILE: firmware/src/hall.h
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef HALL_H_
#define HALL_H_
extern volatile uint16_t lasthallpos;
extern volatile uint16_t hallpos;
void initHALL();
#endif /* HALL_H_ */
================================================
FILE: firmware/src/input.c
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include
#include
#include
#include "pwm.h"
#include "encoder.h"
#include "pid.h"
#include "input.h"
#include "configuration.h"
volatile uint16_t updateCtr;
volatile uint16_t motor_running;
void initLeds()
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
//LED0 == ENABLE Led
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//LED1 == ERROR Led
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//LED2 == POWER Led
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);
}
void initStepDirInput()
{
GPIO_InitTypeDef GPIO_InitStructure;
//PA6 as STEP input
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PA7 as DIR pin
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PA5 as ENA pin
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource6); //STEP pin
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource5); //ENA pin
EXTI_InitTypeDef EXTI_initStructure;
EXTI_initStructure.EXTI_Line = EXTI_Line6;
EXTI_initStructure.EXTI_Mode = EXTI_Mode_Interrupt;
if(!is_step_inverted)
EXTI_initStructure.EXTI_Trigger = EXTI_Trigger_Rising;
else
EXTI_initStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_initStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_initStructure);
EXTI_initStructure.EXTI_Line = EXTI_Line5;
EXTI_initStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_initStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_initStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_initStructure);
NVIC_InitTypeDef nvicStructure;
nvicStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;
nvicStructure.NVIC_IRQChannelSubPriority = 2;
nvicStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvicStructure);
}
void EXTI9_5_IRQHandler()
{
uint8_t ena,idir;
if(EXTI_GetITStatus(EXTI_Line5)!= RESET)
{
//ENA PIN INTERRUPT
if(!is_ena_inverted)
ena = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);
else
ena = (~(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5)))&1;
if(ena && !motor_running)
{
//enable rose. Start
pid_requested_position = encoder_count; //reset the desired position to current.
pwm_motorStart();
ENABLE_LED_ON;
ERROR_LED_OFF;
}
else if(!ena && motor_running)
{
//enable fell. Stop.
pwm_motorStop();
ENABLE_LED_OFF;
}
else if(!ena)
{
ENABLE_LED_OFF;
}
EXTI_ClearITPendingBit(EXTI_Line5);
}
if(EXTI_GetITStatus(EXTI_Line6)!= RESET)
{
//STEP PIN INTERRUPT
if(!is_dir_inverted)
idir = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7);
else
idir = (~(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7)))&1;
if(idir)
{
pid_requested_position+=s.encoder_counts_per_step;
}
else
pid_requested_position-=s.encoder_counts_per_step;
EXTI_ClearITPendingBit(EXTI_Line6);
}
}
void initPWMInput()
{
GPIO_InitTypeDef GPIO_InitStructure;
//TIM3 as PWM input
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PA7 as DIR pin
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
//PA5 as ENA pin
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &GPIO_InitStructure);
EXTI_InitTypeDef EXTI_initStructure;
EXTI_initStructure.EXTI_Line = EXTI_Line5;
EXTI_initStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_initStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
EXTI_initStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_initStructure);
NVIC_InitTypeDef nvicStructure;
nvicStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
nvicStructure.NVIC_IRQChannelPreemptionPriority = 0;
nvicStructure.NVIC_IRQChannelSubPriority = 2;
nvicStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&nvicStructure);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.TIM_Prescaler = 1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 65535;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ICInitTypeDef TIM_ICInit;
if(!is_step_inverted)
TIM_ICInit.TIM_ICPolarity = TIM_ICPolarity_Rising;
else
TIM_ICInit.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInit.TIM_ICFilter = 5;
TIM_ICInit.TIM_Channel = TIM_Channel_1;
TIM_ICInit.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInit.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_PWMIConfig(TIM3, &TIM_ICInit);
TIM_CCxCmd(TIM3, TIM_Channel_1, ENABLE);
TIM_CCxCmd(TIM3, TIM_Channel_2, ENABLE);
TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);
TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_Update, ENABLE);
TIM_Cmd(TIM3,ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM3_IRQHandler(void) {
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
if(s.inputMethod==inputMethod_stepDir)
{
updatePid();
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
else
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
updateCtr++;
if(updateCtr>50)
{
//pwm_motorStop();
//ERROR_LED_ON;
}
}
}
if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)
{
uint16_t tim3_dc = TIM3->CCR2;
uint16_t tim3_per = TIM3->CCR1;
uint16_t DC;
if(!is_dir_inverted)
dir = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7);
else
dir = (~(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7)))&1;
if(tim3_per>0 && tim3_per>tim3_dc)
{
DC = ((uint32_t)(BLDC_CHOPPER_PERIOD*tim3_dc)/(uint32_t)tim3_per);
}
else
DC=0;
//if(DC
extern volatile uint8_t dir;
#define POWER_LED_ON GPIO_SetBits(GPIOC, GPIO_Pin_15);
#define POWER_LED_OFF GPIO_ResetBits(GPIOC, GPIO_Pin_15);
#define ENABLE_LED_ON GPIO_SetBits(GPIOC, GPIO_Pin_13);
#define ENABLE_LED_OFF GPIO_ResetBits(GPIOC, GPIO_Pin_13);
#define ERROR_LED_ON GPIO_SetBits(GPIOC, GPIO_Pin_14);
#define ERROR_LED_OFF GPIO_ResetBits(GPIOC, GPIO_Pin_14);
extern volatile uint16_t updateCtr;
extern volatile uint16_t motor_running;
void initStepDirInput();
void initPWMInput();
void initLeds();
#endif /* INPUT_H_ */
================================================
FILE: firmware/src/main.c
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include "pwm.h"
#include "hall.h"
#include "adc.h"
#include "input.h"
#include "encoder.h"
#include "pid.h"
#include "usart.h"
#include "configuration.h"
#include "input.h"
#include "utils.h"
volatile uint8_t dir;
volatile servoConfig s;
int main() {
motor_running=0;
updateCtr=0;
dir=1;
FLASH_Unlock();
getConfig();
#ifdef SINUSOID_DRIVE
//sinusoid always needs encoder.
s.commutationMethod = commutationMethod_Encoder;
#endif
initUSART(s.usart_baud);
printConfiguration();
systickInit(1000);
initPWM();
initADC();
if( s.commutationMethod == commutationMethod_HALL)
{
initHALL();
}
if(s.inputMethod == inputMethod_stepDir)
{
initStepDirInput();
}
else if (s.inputMethod == inputMethod_pwmVelocity)
{
initPWMInput();
}
if(s.inputMethod == inputMethod_stepDir || s.commutationMethod == commutationMethod_Encoder)
{
initEncoder();
}
if(s.inputMethod == inputMethod_stepDir)
{
initPid();
}
initLeds();
POWER_LED_ON;
uint8_t ena;
//check if ENA is on already at start. If it is, start motor.
if(!is_ena_inverted)
ena = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5);
else
ena = (~(GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5)))&1;
if(ena)
{
pwm_motorStart();
ENABLE_LED_ON;
}
//two different types of main loops depending on commutation method
if(s.commutationMethod == commutationMethod_Encoder || s.inputMethod == inputMethod_stepDir)
{
while (1)
{
getEncoderCount();
#ifdef SINUSOID_DRIVE
pwm_setDutyCycle();
#endif
#ifndef SINUSOID_DRIVE
//check commutation position for trapezoid commutation if done by encoder
if(s.commutationMethod == commutationMethod_Encoder && encoder_commutation_pos != encoder_commutation_table[encoder_shaft_pos])
{
encoder_commutation_pos = encoder_commutation_table[encoder_shaft_pos];
pwm_Commute(encoder_commutation_pos);
}
#endif
if(serial_stream_enabled && DMA_GetFlagStatus(DMA1_FLAG_TC2) == SET)
{
//dma transfer is complete
usart_send_stream();
}
}
}
else
{
while(1)
{
//commutation handled by HALL sensor interrupts in this case
pwm_setDutyCycle();
if(serial_stream_enabled && DMA_GetFlagStatus(DMA1_FLAG_TC2) == SET)
{
//dma transfer is complete
usart_send_stream();
}
}
}
}
================================================
FILE: firmware/src/pid.c
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
Pid loop is based on F103ServoDrive project of Mihai.
http://www.cnczone.com/forums/open-source-controller-boards/283428-cnc.html
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include
#include "pid.h"
#include "pwm.h"
#include "hall.h"
#include "encoder.h"
#include "input.h"
#include "configuration.h"
int32_t position_error;
int32_t pid_requested_position;
int32_t pid_last_requested_position;
int32_t pid_last_requested_position_delta;
volatile int32_t pid_integrated_error;
int32_t pid_prev_position_error;
uint32_t max_error; //statistics
volatile uint16_t duty;
void initPid()
{
pid_requested_position=encoder_count;
pid_integrated_error = 0;
pid_prev_position_error =0;
//TIM3 used for pid loop timing.
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler = 72; //1MHz counter
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = PID_TIM_PERIOD; //4kHz update interval
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
TIM_Cmd(TIM3, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//This is called from TIM3 update interrupt. defined in input.c
void updatePid()
{
uint32_t abs_position_error;
int32_t position_delta;
int32_t position_delta_delta;
//getEncoderCount(); //this is dangerous to call from interrupt
if (!motor_running)
{
pid_integrated_error=0;
return;
}
position_error = encoder_count - pid_requested_position;
position_delta= pid_requested_position - pid_last_requested_position;
position_delta_delta = position_delta - pid_last_requested_position_delta;
pid_last_requested_position = pid_requested_position;
pid_last_requested_position_delta = position_delta;
abs_position_error = abs(position_error);
if(abs_position_error < s.pid_deadband)
{
position_error=0;
}
else if (position_error > 0)
position_error -= s.pid_deadband;
else
position_error += s.pid_deadband;
if(abs_position_error > max_error)
max_error = abs_position_error;
if (abs_position_error > s.max_error)
{
pwm_motorStop();
ERROR_LED_ON;
return;
}
//P
int32_t output = position_error * s.pid_Kp;
//I
pid_integrated_error += position_error * s.pid_Ki;
if (pid_integrated_error > 400000)
pid_integrated_error = 400000;
if (pid_integrated_error < -400000)
pid_integrated_error = -400000;
output += pid_integrated_error;
//D
output += (position_error - pid_prev_position_error) * s.pid_Kd;
pid_prev_position_error = position_error;
//FF1
output += position_delta * s.pid_FF1;
//FF2
output += position_delta_delta * s.pid_FF2;
output /= 100; //provide larger dynamic range for pid. (without this, having pid_Ki = 1 was enough for oscillation.
//limit output power
if (output > MAX_DUTY)
output = MAX_DUTY;
if (output < -MAX_DUTY)
output = -MAX_DUTY;
if(output>0)
{
dir=0;
}
else
{
dir=1;
}
duty = abs(output);
pwm_setDutyCycle();
}
================================================
FILE: firmware/src/pid.h
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
Pid loop is based on F103ServoDrive project of Mihai.
http://www.cnczone.com/forums/open-source-controller-boards/283428-cnc.html
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef PID_H_
#define PID_H_
#include "configuration.h"
#include
void initPid();
void updatePid();
extern volatile servoConfig s;
extern int32_t position_error;
extern int32_t pid_requested_position;
extern int32_t pid_last_requested_position;
extern uint32_t pid_max_pos_error;
extern int32_t pid_last_requested_position_delta;
extern volatile int32_t pid_integrated_error;
extern int32_t pid_prev_position_error;
extern uint32_t max_error; //statistics
extern volatile uint16_t duty;
#endif /* PID_H_ */
================================================
FILE: firmware/src/pwm.c
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
Original PWM commutation tables and ideas on PWM commutation from a great article in http://www.mikrocontroller.net/articles/STM32_BLDC_Control_with_HALL_Sensor
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include
#include
#include "pwm.h"
#include "input.h"
#include "hall.h"
#include "encoder.h"
#include "configuration.h"
#include "adc.h"
#include "pid.h"
#define FALSE 0
#define TRUE 1
volatile uint8_t errorInCommutation;
static const uint8_t BLDC_BRIDGE_STATE_BACKWARD[8][6] = // Motor step
{
{ FALSE,FALSE , FALSE,FALSE , FALSE,FALSE }, // //000
{ FALSE,FALSE, TRUE,FALSE, FALSE,TRUE },
{ TRUE,FALSE, FALSE,TRUE, FALSE,FALSE },
{ TRUE,FALSE, FALSE,FALSE, FALSE,TRUE },
{ FALSE,TRUE, FALSE,FALSE, TRUE,FALSE },
{ FALSE,TRUE, TRUE,FALSE, FALSE,FALSE },
{ FALSE,FALSE, FALSE,TRUE, TRUE,FALSE },
{ FALSE,FALSE , FALSE,FALSE , FALSE,FALSE }, // //111
};
static const uint8_t BLDC_BRIDGE_STATE_VORWARD[8][6] = // Motor step
{
{ FALSE,FALSE , FALSE,FALSE , FALSE,FALSE }, // 0 //000
{ FALSE,FALSE, FALSE,TRUE, TRUE,FALSE },
{ FALSE,TRUE, TRUE,FALSE, FALSE,FALSE },
{ FALSE,TRUE, FALSE,FALSE, TRUE,FALSE },
{ TRUE,FALSE, FALSE,FALSE, FALSE,TRUE },
{ TRUE,FALSE, FALSE,TRUE, FALSE,FALSE },
{ FALSE,FALSE, TRUE,FALSE, FALSE,TRUE },
{ FALSE,FALSE , FALSE,FALSE , FALSE,FALSE }, // 0 //111
};
void UpdatePWMChannels(uint8_t BL1,uint8_t BL2,uint8_t BL3,uint8_t BH1,uint8_t BH2,uint8_t BH3);
void initPWM()
{
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
//initialize Tim1 PWM outputs
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
// Time Base configuration
TIM_TimeBaseStructure.TIM_Prescaler = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = BLDC_CHOPPER_PERIOD;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
// Channel 1, 2, 3 – set to PWM mode - all 6 outputs
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0; // initialize to zero output
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Set;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
TIM_OC2Init(TIM1, &TIM_OCInitStructure);
TIM_OC3Init(TIM1, &TIM_OCInitStructure);
TIM_OC4Init(TIM1, &TIM_OCInitStructure); //for ADC
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
// DeadTime[ns] = value * (1/SystemCoreFreq) (on 72MHz: 7 is 98ns)
TIM_BDTRInitStructure.TIM_DeadTime = BLDC_NOL;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
//no break functionality
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
//Commutation event mapped to TIM4 - We are not using commute event, but interrupt from Hall timer directly to commute.
//Not optimal solution?
//TIM_SelectInputTrigger(TIM1, TIM_TS_ITR3);
TIM_ITConfig(TIM1, TIM_IT_CC4, ENABLE); //adc sampling interrupt
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM1, ENABLE);
// enable motor timer main output (the bridge signals)
TIM_CtrlPWMOutputs(TIM1, ENABLE);
pwm_motorStop();
}
void TIM1_CC_IRQHandler(void)
{
if (TIM_GetITStatus(TIM1, TIM_IT_CC4) != RESET)
{
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
TIM_ClearITPendingBit(TIM1, TIM_IT_CC4);
}
}
#ifndef SINUSOID_DRIVE
void pwm_setDutyCycle()
{
static uint8_t prevdir=0;
if(!motor_running)
return;
if(dir!=prevdir)
{
pwm_InitialBLDCCommutation();
}
prevdir=dir;
uint16_t d = duty;
if(d>MAX_DUTY) d = MAX_DUTY; //this is absolute MAX
if(d>max_duty) d = max_duty; //this is maximum set by ADC current limiting
TIM1->CCR1 = d;
TIM1->CCR2 = d;
TIM1->CCR3 = d;
TIM1->CCR4 = d>>1; //get the ADC conversion on the half duty cycle.
}
#else
void pwm_setDutyCycle()
{
if(!motor_running)
return;
uint16_t pos[3];
pos[0] = getCommutationPos(0);
pos[1] = getCommutationPos(1);
pos[2] = getCommutationPos(2);
uint16_t d = duty;
if(d>MAX_DUTY) d = MAX_DUTY; //this is absolute MAX
if(d>max_duty) d = max_duty; //this is maximum set by ADC current limiting
TIM1->CCR1 = (int32_t)sine_table[pos[0]]*d/SINE_TABLE_MAX+ZERO_DUTY;
TIM1->CCR2 = (int32_t)sine_table[pos[1]]*d/SINE_TABLE_MAX+ZERO_DUTY;
TIM1->CCR3 = (int32_t)sine_table[pos[2]]*d/SINE_TABLE_MAX+ZERO_DUTY;
TIM1->CCR4 = d>>1; //get the ADC conversion on the half duty cycle.
}
#endif
void pwm_motorStart()
{
motor_running=1;
#ifndef SINUSOID_DRIVE
pwm_InitialBLDCCommutation();
TIM_ITConfig(TIM4, TIM_IT_CC1 | TIM_IT_CC2, ENABLE); //enable HALL interrupts
#else
//on sinusoid drive, all channels enabled at once
TIM_SelectOCxM(TIM1, TIM_Channel_1, TIM_OCMode_PWM1);
TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable);
TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Enable);
TIM_SelectOCxM(TIM1, TIM_Channel_2, TIM_OCMode_PWM1);
TIM_CCxCmd(TIM1, TIM_Channel_2, TIM_CCx_Enable);
TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Enable);
TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_OCMode_PWM1);
TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Enable);
TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Enable);
#endif
}
void pwm_motorStop()
{
motor_running=0;
TIM1->CCR1 = 0;
TIM1->CCR2 = 0;
TIM1->CCR3 = 0;
TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Disable);
TIM_CCxCmd(TIM1, TIM_Channel_2, TIM_CCx_Disable);
TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Disable);
TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Disable);
TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Disable);
TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Disable);
#ifndef SINUSOID_DRIVE
TIM_ITConfig(TIM4, TIM_IT_CC1 | TIM_IT_CC2, DISABLE); //disable HALL interrupts, no commutation!
#endif
}
#ifndef SINUSOID_DRIVE
void pwm_InitialBLDCCommutation()
{
uint16_t newhallpos;
if(s.commutationMethod == commutationMethod_HALL)
{
//this function is called when forced commutation is required, eg when starting or when anomalies are detected.
newhallpos = ((GPIO_ReadInputData(GPIOB)>>6) & 0x0007);
hallpos = newhallpos;
pwm_Commute(hallpos);
return;
}
else
{
encoder_commutation_pos = encoder_commutation_table[encoder_shaft_pos];
pwm_Commute(encoder_commutation_pos);
return;
}
}
void pwm_Commute(uint8_t comm_pos)
{
uint8_t BH1,BH2,BH3,BL1,BL2,BL3;
if(dir)
{
BH1 = BLDC_BRIDGE_STATE_VORWARD[comm_pos][0];
BL1 = BLDC_BRIDGE_STATE_VORWARD[comm_pos][1];
BH2 = BLDC_BRIDGE_STATE_VORWARD[comm_pos][2];
BL2 = BLDC_BRIDGE_STATE_VORWARD[comm_pos][3];
BH3 = BLDC_BRIDGE_STATE_VORWARD[comm_pos][4];
BL3 = BLDC_BRIDGE_STATE_VORWARD[comm_pos][5];
}
else
{
BH1 = BLDC_BRIDGE_STATE_BACKWARD[comm_pos][0];
BL1 = BLDC_BRIDGE_STATE_BACKWARD[comm_pos][1];
BH2 = BLDC_BRIDGE_STATE_BACKWARD[comm_pos][2];
BL2 = BLDC_BRIDGE_STATE_BACKWARD[comm_pos][3];
BH3 = BLDC_BRIDGE_STATE_BACKWARD[comm_pos][4];
BL3 = BLDC_BRIDGE_STATE_BACKWARD[comm_pos][5];
}
UpdatePWMChannels(BL1,BL2,BL3,BH1,BH2,BH3);
}
void UpdatePWMChannels(uint8_t BL1,uint8_t BL2,uint8_t BL3,uint8_t BH1,uint8_t BH2,uint8_t BH3)
{
//THIS NEEDS OPTIMIZATION!
// **** this is with active freewheeling ****
// Bridge FETs for Motor Phase U
if (BH1) {
// PWM at low side FET of bridge U
// active freewheeling at high side FET of bridge U
// if low side FET is in PWM off mode then the hide side FET
// is ON for active freewheeling. This mode needs correct definition
// of dead time otherwise we have shoot-through problems
TIM_SelectOCxM(TIM1, TIM_Channel_1, TIM_OCMode_PWM1);
TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Enable);
TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Enable);
} else {
// Low side FET: OFF
TIM_CCxCmd(TIM1, TIM_Channel_1, TIM_CCx_Disable);
if (BL1){
// High side FET: ON
TIM_SelectOCxM(TIM1, TIM_Channel_1, TIM_ForcedAction_Active);
TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Enable);
} else {
// High side FET: OFF
TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Disable);
}
}
// Bridge FETs for Motor Phase V
if (BH2) {
TIM_SelectOCxM(TIM1, TIM_Channel_2, TIM_OCMode_PWM1);
TIM_CCxCmd(TIM1, TIM_Channel_2, TIM_CCx_Enable);
TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Enable);
} else {
TIM_CCxCmd(TIM1, TIM_Channel_2, TIM_CCx_Disable);
if (BL2){
TIM_SelectOCxM(TIM1, TIM_Channel_2, TIM_ForcedAction_Active);
TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Enable);
} else {
TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Disable);
}
}
// Bridge FETs for Motor Phase W
if (BH3) {
TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_OCMode_PWM1);
TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Enable);
TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Enable);
} else {
TIM_CCxCmd(TIM1, TIM_Channel_3, TIM_CCx_Disable);
if (BL3){
TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_ForcedAction_Active);
TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Enable);
} else {
TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Disable);
}
}
}
#endif
================================================
FILE: firmware/src/pwm.h
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef PWM_H
#define PWM_H
#include "configuration.h"
static const uint8_t commutation_sequence[6] = {1,3,2,6,4,5};//{001,011,010,110,100,101}
static const uint8_t pos_in_sequence[8] = {0,1,3,2,5,6,4,0};
extern volatile servoConfig s;
void enableHallCommutateSignal();
void disableHallCommutateSignal();
void initPWM();
void pwm_BLDCMotorPrepareCommutation();
void pwm_Commute(uint8_t comm_pos);
void pwm_InitialBLDCCommutation();
void pwm_setDutyCycle();
void pwm_motorStart();
void pwm_motorStop();
#endif
================================================
FILE: firmware/src/usart.c
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include
#include
#include
#include
#include
#include
#include "usart.h"
#include "pid.h"
#include "pwm.h"
#include "encoder.h"
#include "adc.h"
#include "hall.h"
#include "configuration.h"
char txbuffer[255];
volatile uint8_t serial_stream_enabled;
char recvbuffer[255];
uint8_t recvctr;
DMA_InitTypeDef DMA_InitStructure;
void initUSART(uint16_t baud)
{
recvctr=0;
serial_stream_enabled=0;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
if(USART == USART1)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO |
RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
else if(USART==USART3)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* Configure USART3_Rx as input floating */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOB, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
USART_InitStructure.USART_BaudRate = baud*100;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART, &USART_InitStructure);
USART_ITConfig(USART, USART_IT_RXNE, ENABLE);
USART_Cmd(USART, ENABLE);
//DMA for USART TX!
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
/* USARTy_Tx_DMA_Channel (triggered by USARTy Tx event) Config */
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004804;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)txbuffer;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = 255;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
//DMA_Cmd(DMA1_Channel2, ENABLE);
}
void usart_startDMA(uint16_t len)
{
DMA_DeInit(DMA1_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = 0x40004804;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)txbuffer;
DMA_InitStructure.DMA_BufferSize = len;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_Init(DMA1_Channel2, &DMA_InitStructure);
DMA_Cmd(DMA1_Channel2, ENABLE);
}
void usart_sendChar(char chr)
{
USART_SendData(USART, chr);
while (USART_GetFlagStatus(USART, USART_FLAG_TXE) == RESET);
}
void usart_sendStr(char *str)
{
while (*str != '\0')
{
usart_sendChar(*str);
str ++;
}
}
void usart_send_stream()
{
// while (DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET)
// {
// }
uint16_t hall;
if (s.commutationMethod == commutationMethod_Encoder)
hall = encoder_commutation_pos;
else
{
hall = hallpos;
}
uint16_t len = sprintf(txbuffer, "STR:%d;%d;%d;%d;%d;%d;%d;%d\r",(int)hall,(int)encoder_count,(int)pid_requested_position,(int)pid_last_requested_position_delta,(int)position_error,(int)ADC_value,(int)TIM1->CCR1,(int)pid_integrated_error);
usart_startDMA(len);
}
void parseUsart()
{
const char delimiters[] = " ";
char *param;
char *value;
if(strstr(recvbuffer, "STREAM")!=NULL)
{
strtok(recvbuffer,delimiters); //first param
value = strtok(NULL,delimiters);
if(strstr(value,"START"))
{
serial_stream_enabled=1;
usart_send_stream();
}
else
serial_stream_enabled=0;
}
if(strstr(recvbuffer, "SET")!=NULL)
{
strtok(recvbuffer,delimiters); //first param
param = strtok(NULL,delimiters);
value = strtok(NULL,delimiters);
if(param!=NULL && value!=NULL)
setConfig(param,atoi(value));
}
if(strstr(recvbuffer, "SAVE")!=NULL)
{
usart_sendStr("Saving:\n\r");
printConfiguration();
writeConfig(s);
usart_sendStr("SAVE OK\n\r");
}
if(strstr(recvbuffer, "GET")!=NULL)
{
//getConfig();
printConfiguration();
}
if(recvctr < 3)
{
uint16_t len =sprintf(txbuffer, "Count: %d, Hall: %d, error: %d, max_error: %d\n\r",(int)encoder_count, (int)hallpos, (int)position_error, (int)max_error);
max_error=0;
usart_startDMA(len);
}
}
void serialInterrupt()
{
char in;
if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
in = (char)USART_ReceiveData(USART3);
recvbuffer[recvctr] = in;
if(in=='\r')
{
parseUsart();
recvctr=0;
}
else
{
//any received character will stop the stream.
serial_stream_enabled=0;
recvctr++;
}
}
}
void USART3_IRQHandler(void)
{
serialInterrupt();
}
void USART1_IRQHandler(void)
{
serialInterrupt();
}
================================================
FILE: firmware/src/usart.h
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef USART_H_
#define USART_H_
#include "configuration.h"
#define USART USART3
void initUSART(uint16_t baud);
void usart_sendChar(char chr);
void usart_sendStr(char *str);
void usart_send_stream();
extern volatile servoConfig s;
extern char txbuffer[255];
extern volatile uint8_t serial_stream_enabled;
#endif /* USART_H_ */
================================================
FILE: firmware/src/utils.c
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
The systick based delay_ms was learned from http://www.micromouseonline.com/2016/02/02/systick-configuration-made-easy-on-the-stm32/
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "utils.h"
#include
#include
#include
void systickInit (uint16_t frequency)
{
RCC_ClocksTypeDef RCC_Clocks;
RCC_GetClocksFreq (&RCC_Clocks);
(void) SysTick_Config (RCC_Clocks.HCLK_Frequency / frequency);
}
static volatile uint32_t ticks;
void SysTick_Handler (void)
{
ticks++;
}
uint32_t millis (void)
{
return ticks;
}
void delay_ms (uint32_t t)
{
uint32_t start, end;
start = millis();
end = start + t;
if (start < end) { while ( (millis() >= start) && (millis() < end)) {
};
}
}
/*
void delay_ms(const uint32_t ms)
{
uint32_t ms2 = ms*STM32_CLOCK_HZ / 1000 / STM32_CYCLES_PER_LOOP;
asm volatile(" mov r0, %[ms2] \n\t"
"loop: subs r0, #1 \n\t"
" bhi loop \n\t"
:
: [ms2] "r" (ms2)
: "r0");
}
*/
================================================
FILE: firmware/src/utils.h
================================================
/*
bldc-drive Cheap and simple brushless DC motor driver designed for CNC applications using STM32 microcontroller.
Copyright (C) 2015 Pekka Roivainen
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef UTILS_H_
#define UTILS_H_
#include
#include
#define STM32_CLOCK_HZ 72000000UL
#define STM32_CYCLES_PER_LOOP 6 // This will need tweaking or calculating
void systickInit (uint16_t frequency);
void delay_ms(const uint32_t ms);
#endif /* UTILS_H_ */
================================================
FILE: firmware/system/include/arm/semihosting.h
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
#ifndef ARM_SEMIHOSTING_H_
#define ARM_SEMIHOSTING_H_
// ----------------------------------------------------------------------------
// Semihosting operations.
enum OperationNumber
{
// Regular operations
SEMIHOSTING_EnterSVC = 0x17,
SEMIHOSTING_ReportException = 0x18,
SEMIHOSTING_SYS_CLOSE = 0x02,
SEMIHOSTING_SYS_CLOCK = 0x10,
SEMIHOSTING_SYS_ELAPSED = 0x30,
SEMIHOSTING_SYS_ERRNO = 0x13,
SEMIHOSTING_SYS_FLEN = 0x0C,
SEMIHOSTING_SYS_GET_CMDLINE = 0x15,
SEMIHOSTING_SYS_HEAPINFO = 0x16,
SEMIHOSTING_SYS_ISERROR = 0x08,
SEMIHOSTING_SYS_ISTTY = 0x09,
SEMIHOSTING_SYS_OPEN = 0x01,
SEMIHOSTING_SYS_READ = 0x06,
SEMIHOSTING_SYS_READC = 0x07,
SEMIHOSTING_SYS_REMOVE = 0x0E,
SEMIHOSTING_SYS_RENAME = 0x0F,
SEMIHOSTING_SYS_SEEK = 0x0A,
SEMIHOSTING_SYS_SYSTEM = 0x12,
SEMIHOSTING_SYS_TICKFREQ = 0x31,
SEMIHOSTING_SYS_TIME = 0x11,
SEMIHOSTING_SYS_TMPNAM = 0x0D,
SEMIHOSTING_SYS_WRITE = 0x05,
SEMIHOSTING_SYS_WRITEC = 0x03,
SEMIHOSTING_SYS_WRITE0 = 0x04,
// Codes returned by SEMIHOSTING_ReportException
ADP_Stopped_ApplicationExit = ((2 << 16) + 38),
ADP_Stopped_RunTimeError = ((2 << 16) + 35),
};
// ----------------------------------------------------------------------------
// SWI numbers and reason codes for RDI (Angel) monitors.
#define AngelSWI_ARM 0x123456
#ifdef __thumb__
#define AngelSWI 0xAB
#else
#define AngelSWI AngelSWI_ARM
#endif
// For thumb only architectures use the BKPT instruction instead of SWI.
#if defined(__ARM_ARCH_7M__) \
|| defined(__ARM_ARCH_7EM__) \
|| defined(__ARM_ARCH_6M__)
#define AngelSWIInsn "bkpt"
#define AngelSWIAsm bkpt
#else
#define AngelSWIInsn "swi"
#define AngelSWIAsm swi
#endif
static inline int
__attribute__ ((always_inline))
call_host (int reason, void* arg)
{
int value;
asm volatile (
" mov r0, %[rsn] \n"
" mov r1, %[arg] \n"
" " AngelSWIInsn " %[swi] \n"
" mov %[val], r0"
: [val] "=r" (value) /* Outputs */
: [rsn] "r" (reason), [arg] "r" (arg), [swi] "i" (AngelSWI) /* Inputs */
: "r0", "r1", "r2", "r3", "ip", "lr", "memory", "cc"
// Clobbers r0 and r1, and lr if in supervisor mode
);
// Accordingly to page 13-77 of ARM DUI 0040D other registers
// can also be clobbered. Some memory positions may also be
// changed by a system call, so they should not be kept in
// registers. Note: we are assuming the manual is right and
// Angel is respecting the APCS.
return value;
}
// ----------------------------------------------------------------------------
// Function used in _exit() to return the status code as Angel exception.
static inline void
__attribute__ ((always_inline,noreturn))
report_exception (int reason)
{
call_host (SEMIHOSTING_ReportException, (void*) reason);
for (;;)
;
}
// ----------------------------------------------------------------------------
#endif // ARM_SEMIHOSTING_H_
================================================
FILE: firmware/system/include/cmsis/README_CMSIS.txt
================================================
* -------------------------------------------------------------------
* Copyright (C) 2011-2014 ARM Limited. All rights reserved.
*
* Date: 17 February 2014
* Revision: V4.00
*
* Project: Cortex Microcontroller Software Interface Standard (CMSIS)
* Title: Release Note for CMSIS
*
* -------------------------------------------------------------------
These files are the CMSIS Core Support and CMSIS DSP Include Files.
To save space, from the complete ARM package (CMSIS-SP-00300-r4p0-00rel0.zip)
only the CMSIS/Include folder was used here.
================================================
FILE: firmware/system/include/cmsis/README_DEVICE.txt
================================================
The stm32f10x.h and system_stm32f10x.h files are from stsw-stm32054.zip,
the folder:
STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x
The cmsis_device.h is added for convenience.
================================================
FILE: firmware/system/include/cmsis/arm_common_tables.h
================================================
/* ----------------------------------------------------------------------
* Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* $Date: 16. October 2013
* $Revision: V1.4.2
*
* Project: CMSIS DSP Library
* Title: arm_common_tables.h
*
* Description: This file has extern declaration for common tables like Bitreverse, reciprocal etc which are used across different functions
*
* Target Processor: Cortex-M4/Cortex-M3
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* - Neither the name of ARM LIMITED nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* -------------------------------------------------------------------- */
#ifndef _ARM_COMMON_TABLES_H
#define _ARM_COMMON_TABLES_H
#include "arm_math.h"
extern const uint16_t armBitRevTable[1024];
extern const q15_t armRecipTableQ15[64];
extern const q31_t armRecipTableQ31[64];
extern const q31_t realCoefAQ31[1024];
extern const q31_t realCoefBQ31[1024];
extern const float32_t twiddleCoef_16[32];
extern const float32_t twiddleCoef_32[64];
extern const float32_t twiddleCoef_64[128];
extern const float32_t twiddleCoef_128[256];
extern const float32_t twiddleCoef_256[512];
extern const float32_t twiddleCoef_512[1024];
extern const float32_t twiddleCoef_1024[2048];
extern const float32_t twiddleCoef_2048[4096];
extern const float32_t twiddleCoef_4096[8192];
#define twiddleCoef twiddleCoef_4096
extern const q31_t twiddleCoefQ31[6144];
extern const q15_t twiddleCoefQ15[6144];
extern const float32_t twiddleCoef_rfft_32[32];
extern const float32_t twiddleCoef_rfft_64[64];
extern const float32_t twiddleCoef_rfft_128[128];
extern const float32_t twiddleCoef_rfft_256[256];
extern const float32_t twiddleCoef_rfft_512[512];
extern const float32_t twiddleCoef_rfft_1024[1024];
extern const float32_t twiddleCoef_rfft_2048[2048];
extern const float32_t twiddleCoef_rfft_4096[4096];
#define ARMBITREVINDEXTABLE__16_TABLE_LENGTH ((uint16_t)20 )
#define ARMBITREVINDEXTABLE__32_TABLE_LENGTH ((uint16_t)48 )
#define ARMBITREVINDEXTABLE__64_TABLE_LENGTH ((uint16_t)56 )
#define ARMBITREVINDEXTABLE_128_TABLE_LENGTH ((uint16_t)208 )
#define ARMBITREVINDEXTABLE_256_TABLE_LENGTH ((uint16_t)440 )
#define ARMBITREVINDEXTABLE_512_TABLE_LENGTH ((uint16_t)448 )
#define ARMBITREVINDEXTABLE1024_TABLE_LENGTH ((uint16_t)1800)
#define ARMBITREVINDEXTABLE2048_TABLE_LENGTH ((uint16_t)3808)
#define ARMBITREVINDEXTABLE4096_TABLE_LENGTH ((uint16_t)4032)
extern const uint16_t armBitRevIndexTable16[ARMBITREVINDEXTABLE__16_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable32[ARMBITREVINDEXTABLE__32_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable64[ARMBITREVINDEXTABLE__64_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable128[ARMBITREVINDEXTABLE_128_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable256[ARMBITREVINDEXTABLE_256_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable512[ARMBITREVINDEXTABLE_512_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable1024[ARMBITREVINDEXTABLE1024_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable2048[ARMBITREVINDEXTABLE2048_TABLE_LENGTH];
extern const uint16_t armBitRevIndexTable4096[ARMBITREVINDEXTABLE4096_TABLE_LENGTH];
/* Tables for Fast Math Sine and Cosine */
extern const float32_t sinTable_f32[FAST_MATH_TABLE_SIZE + 1];
extern const q31_t sinTable_q31[FAST_MATH_TABLE_SIZE + 1];
extern const q15_t sinTable_q15[FAST_MATH_TABLE_SIZE + 1];
#endif /* ARM_COMMON_TABLES_H */
================================================
FILE: firmware/system/include/cmsis/arm_const_structs.h
================================================
/* ----------------------------------------------------------------------
* Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*
* $Date: 16. October 2013
* $Revision: V1.4.2
*
* Project: CMSIS DSP Library
* Title: arm_const_structs.h
*
* Description: This file has constant structs that are initialized for
* user convenience. For example, some can be given as
* arguments to the arm_cfft_f32() function.
*
* Target Processor: Cortex-M4/Cortex-M3
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* - Neither the name of ARM LIMITED nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* -------------------------------------------------------------------- */
#ifndef _ARM_CONST_STRUCTS_H
#define _ARM_CONST_STRUCTS_H
#include "arm_math.h"
#include "arm_common_tables.h"
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len16;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len32;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len64;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len128;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len256;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len512;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len1024;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len2048;
extern const arm_cfft_instance_f32 arm_cfft_sR_f32_len4096;
#endif
================================================
FILE: firmware/system/include/cmsis/arm_math.h
================================================
/* ----------------------------------------------------------------------
* Copyright (C) 2010-2014 ARM Limited. All rights reserved.
*
* $Date: 20. February 2014
* $Revision: V1.4.2
*
* Project: CMSIS DSP Library
* Title: arm_math.h
*
* Description: Public header file for CMSIS DSP Library
*
* Target Processor: Cortex-M4/Cortex-M3/Cortex-M0
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* - Neither the name of ARM LIMITED nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* -------------------------------------------------------------------- */
/**
\mainpage CMSIS DSP Software Library
*
* Introduction
*
* This user manual describes the CMSIS DSP software library,
* a suite of common signal processing functions for use on Cortex-M processor based devices.
*
* The library is divided into a number of functions each covering a specific category:
* - Basic math functions
* - Fast math functions
* - Complex math functions
* - Filters
* - Matrix functions
* - Transforms
* - Motor control functions
* - Statistical functions
* - Support functions
* - Interpolation functions
*
* The library has separate functions for operating on 8-bit integers, 16-bit integers,
* 32-bit integer and 32-bit floating-point values.
*
* Using the Library
*
* The library installer contains prebuilt versions of the libraries in the Lib folder.
* - arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4)
* - arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4)
* - arm_cortexM4l_math.lib (Little endian on Cortex-M4)
* - arm_cortexM4b_math.lib (Big endian on Cortex-M4)
* - arm_cortexM3l_math.lib (Little endian on Cortex-M3)
* - arm_cortexM3b_math.lib (Big endian on Cortex-M3)
* - arm_cortexM0l_math.lib (Little endian on Cortex-M0)
* - arm_cortexM0b_math.lib (Big endian on Cortex-M3)
*
* The library functions are declared in the public file arm_math.h which is placed in the Include folder.
* Simply include this file and link the appropriate library in the application and begin calling the library functions. The Library supports single
* public header file arm_math.h for Cortex-M4/M3/M0 with little endian and big endian. Same header file will be used for floating point unit(FPU) variants.
* Define the appropriate pre processor MACRO ARM_MATH_CM4 or ARM_MATH_CM3 or
* ARM_MATH_CM0 or ARM_MATH_CM0PLUS depending on the target processor in the application.
*
* Examples
*
* The library ships with a number of examples which demonstrate how to use the library functions.
*
* Toolchain Support
*
* The library has been developed and tested with MDK-ARM version 4.60.
* The library is being tested in GCC and IAR toolchains and updates on this activity will be made available shortly.
*
* Building the Library
*
* The library installer contains a project file to re build libraries on MDK-ARM Tool chain in the CMSIS\\DSP_Lib\\Source\\ARM folder.
* - arm_cortexM_math.uvproj
*
*
* The libraries can be built by opening the arm_cortexM_math.uvproj project in MDK-ARM, selecting a specific target, and defining the optional pre processor MACROs detailed above.
*
* Pre-processor Macros
*
* Each library project have differant pre-processor macros.
*
* - UNALIGNED_SUPPORT_DISABLE:
*
* Define macro UNALIGNED_SUPPORT_DISABLE, If the silicon does not support unaligned memory access
*
* - ARM_MATH_BIG_ENDIAN:
*
* Define macro ARM_MATH_BIG_ENDIAN to build the library for big endian targets. By default library builds for little endian targets.
*
* - ARM_MATH_MATRIX_CHECK:
*
* Define macro ARM_MATH_MATRIX_CHECK for checking on the input and output sizes of matrices
*
* - ARM_MATH_ROUNDING:
*
* Define macro ARM_MATH_ROUNDING for rounding on support functions
*
* - ARM_MATH_CMx:
*
* Define macro ARM_MATH_CM4 for building the library on Cortex-M4 target, ARM_MATH_CM3 for building library on Cortex-M3 target
* and ARM_MATH_CM0 for building library on cortex-M0 target, ARM_MATH_CM0PLUS for building library on cortex-M0+ target.
*
* - __FPU_PRESENT:
*
* Initialize macro __FPU_PRESENT = 1 when building on FPU supported Targets. Enable this macro for M4bf and M4lf libraries
*
* Copyright Notice
*
* Copyright (C) 2010-2013 ARM Limited. All rights reserved.
*/
/**
* @defgroup groupMath Basic Math Functions
*/
/**
* @defgroup groupFastMath Fast Math Functions
* This set of functions provides a fast approximation to sine, cosine, and square root.
* As compared to most of the other functions in the CMSIS math library, the fast math functions
* operate on individual values and not arrays.
* There are separate functions for Q15, Q31, and floating-point data.
*
*/
/**
* @defgroup groupCmplxMath Complex Math Functions
* This set of functions operates on complex data vectors.
* The data in the complex arrays is stored in an interleaved fashion
* (real, imag, real, imag, ...).
* In the API functions, the number of samples in a complex array refers
* to the number of complex values; the array contains twice this number of
* real values.
*/
/**
* @defgroup groupFilters Filtering Functions
*/
/**
* @defgroup groupMatrix Matrix Functions
*
* This set of functions provides basic matrix math operations.
* The functions operate on matrix data structures. For example,
* the type
* definition for the floating-point matrix structure is shown
* below:
*
* typedef struct
* {
* uint16_t numRows; // number of rows of the matrix.
* uint16_t numCols; // number of columns of the matrix.
* float32_t *pData; // points to the data of the matrix.
* } arm_matrix_instance_f32;
*
* There are similar definitions for Q15 and Q31 data types.
*
* The structure specifies the size of the matrix and then points to
* an array of data. The array is of size numRows X numCols
* and the values are arranged in row order. That is, the
* matrix element (i, j) is stored at:
*
* pData[i*numCols + j]
*
*
* \par Init Functions
* There is an associated initialization function for each type of matrix
* data structure.
* The initialization function sets the values of the internal structure fields.
* Refer to the function arm_mat_init_f32(), arm_mat_init_q31()
* and arm_mat_init_q15() for floating-point, Q31 and Q15 types, respectively.
*
* \par
* Use of the initialization function is optional. However, if initialization function is used
* then the instance structure cannot be placed into a const data section.
* To place the instance structure in a const data
* section, manually initialize the data structure. For example:
*
* arm_matrix_instance_f32 S = {nRows, nColumns, pData};
* arm_matrix_instance_q31 S = {nRows, nColumns, pData};
* arm_matrix_instance_q15 S = {nRows, nColumns, pData};
*
* where nRows specifies the number of rows, nColumns
* specifies the number of columns, and pData points to the
* data array.
*
* \par Size Checking
* By default all of the matrix functions perform size checking on the input and
* output matrices. For example, the matrix addition function verifies that the
* two input matrices and the output matrix all have the same number of rows and
* columns. If the size check fails the functions return:
*
* ARM_MATH_SIZE_MISMATCH
*
* Otherwise the functions return
*
* ARM_MATH_SUCCESS
*
* There is some overhead associated with this matrix size checking.
* The matrix size checking is enabled via the \#define
*
* ARM_MATH_MATRIX_CHECK
*
* within the library project settings. By default this macro is defined
* and size checking is enabled. By changing the project settings and
* undefining this macro size checking is eliminated and the functions
* run a bit faster. With size checking disabled the functions always
* return ARM_MATH_SUCCESS.
*/
/**
* @defgroup groupTransforms Transform Functions
*/
/**
* @defgroup groupController Controller Functions
*/
/**
* @defgroup groupStats Statistics Functions
*/
/**
* @defgroup groupSupport Support Functions
*/
/**
* @defgroup groupInterpolation Interpolation Functions
* These functions perform 1- and 2-dimensional interpolation of data.
* Linear interpolation is used for 1-dimensional data and
* bilinear interpolation is used for 2-dimensional data.
*/
/**
* @defgroup groupExamples Examples
*/
#ifndef _ARM_MATH_H
#define _ARM_MATH_H
#define __CMSIS_GENERIC /* disable NVIC and Systick functions */
#if defined (ARM_MATH_CM4)
#include "core_cm4.h"
#elif defined (ARM_MATH_CM3)
#include "core_cm3.h"
#elif defined (ARM_MATH_CM0)
#include "core_cm0.h"
#define ARM_MATH_CM0_FAMILY
#elif defined (ARM_MATH_CM0PLUS)
#include "core_cm0plus.h"
#define ARM_MATH_CM0_FAMILY
#else
#include "ARMCM4.h"
#warning "Define either ARM_MATH_CM4 OR ARM_MATH_CM3...By Default building on ARM_MATH_CM4....."
#endif
#undef __CMSIS_GENERIC /* enable NVIC and Systick functions */
#include "string.h"
#include "math.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Macros required for reciprocal calculation in Normalized LMS
*/
#define DELTA_Q31 (0x100)
#define DELTA_Q15 0x5
#define INDEX_MASK 0x0000003F
#ifndef PI
#define PI 3.14159265358979f
#endif
/**
* @brief Macros required for SINE and COSINE Fast math approximations
*/
#define FAST_MATH_TABLE_SIZE 512
#define FAST_MATH_Q31_SHIFT (32 - 10)
#define FAST_MATH_Q15_SHIFT (16 - 10)
#define CONTROLLER_Q31_SHIFT (32 - 9)
#define TABLE_SIZE 256
#define TABLE_SPACING_Q31 0x400000
#define TABLE_SPACING_Q15 0x80
/**
* @brief Macros required for SINE and COSINE Controller functions
*/
/* 1.31(q31) Fixed value of 2/360 */
/* -1 to +1 is divided into 360 values so total spacing is (2/360) */
#define INPUT_SPACING 0xB60B61
/**
* @brief Macro for Unaligned Support
*/
#ifndef UNALIGNED_SUPPORT_DISABLE
#define ALIGN4
#else
#if defined (__GNUC__)
#define ALIGN4 __attribute__((aligned(4)))
#else
#define ALIGN4 __align(4)
#endif
#endif /* #ifndef UNALIGNED_SUPPORT_DISABLE */
/**
* @brief Error status returned by some functions in the library.
*/
typedef enum
{
ARM_MATH_SUCCESS = 0, /**< No error */
ARM_MATH_ARGUMENT_ERROR = -1, /**< One or more arguments are incorrect */
ARM_MATH_LENGTH_ERROR = -2, /**< Length of data buffer is incorrect */
ARM_MATH_SIZE_MISMATCH = -3, /**< Size of matrices is not compatible with the operation. */
ARM_MATH_NANINF = -4, /**< Not-a-number (NaN) or infinity is generated */
ARM_MATH_SINGULAR = -5, /**< Generated by matrix inversion if the input matrix is singular and cannot be inverted. */
ARM_MATH_TEST_FAILURE = -6 /**< Test Failed */
} arm_status;
/**
* @brief 8-bit fractional data type in 1.7 format.
*/
typedef int8_t q7_t;
/**
* @brief 16-bit fractional data type in 1.15 format.
*/
typedef int16_t q15_t;
/**
* @brief 32-bit fractional data type in 1.31 format.
*/
typedef int32_t q31_t;
/**
* @brief 64-bit fractional data type in 1.63 format.
*/
typedef int64_t q63_t;
/**
* @brief 32-bit floating-point type definition.
*/
typedef float float32_t;
/**
* @brief 64-bit floating-point type definition.
*/
typedef double float64_t;
/**
* @brief definition to read/write two 16 bit values.
*/
#if defined __CC_ARM
#define __SIMD32_TYPE int32_t __packed
#define CMSIS_UNUSED __attribute__((unused))
#elif defined __ICCARM__
#define CMSIS_UNUSED
#define __SIMD32_TYPE int32_t __packed
#elif defined __GNUC__
#define __SIMD32_TYPE int32_t
#define CMSIS_UNUSED __attribute__((unused))
#elif defined __CSMC__ /* Cosmic */
#define CMSIS_UNUSED
#define __SIMD32_TYPE int32_t
#else
#error Unknown compiler
#endif
#define __SIMD32(addr) (*(__SIMD32_TYPE **) & (addr))
#define __SIMD32_CONST(addr) ((__SIMD32_TYPE *)(addr))
#define _SIMD32_OFFSET(addr) (*(__SIMD32_TYPE *) (addr))
#define __SIMD64(addr) (*(int64_t **) & (addr))
#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY)
/**
* @brief definition to pack two 16 bit values.
*/
#define __PKHBT(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0x0000FFFF) | \
(((int32_t)(ARG2) << ARG3) & (int32_t)0xFFFF0000) )
#define __PKHTB(ARG1, ARG2, ARG3) ( (((int32_t)(ARG1) << 0) & (int32_t)0xFFFF0000) | \
(((int32_t)(ARG2) >> ARG3) & (int32_t)0x0000FFFF) )
#endif
/**
* @brief definition to pack four 8 bit values.
*/
#ifndef ARM_MATH_BIG_ENDIAN
#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v0) << 0) & (int32_t)0x000000FF) | \
(((int32_t)(v1) << 8) & (int32_t)0x0000FF00) | \
(((int32_t)(v2) << 16) & (int32_t)0x00FF0000) | \
(((int32_t)(v3) << 24) & (int32_t)0xFF000000) )
#else
#define __PACKq7(v0,v1,v2,v3) ( (((int32_t)(v3) << 0) & (int32_t)0x000000FF) | \
(((int32_t)(v2) << 8) & (int32_t)0x0000FF00) | \
(((int32_t)(v1) << 16) & (int32_t)0x00FF0000) | \
(((int32_t)(v0) << 24) & (int32_t)0xFF000000) )
#endif
/**
* @brief Clips Q63 to Q31 values.
*/
static __INLINE q31_t clip_q63_to_q31(
q63_t x)
{
return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ?
((0x7FFFFFFF ^ ((q31_t) (x >> 63)))) : (q31_t) x;
}
/**
* @brief Clips Q63 to Q15 values.
*/
static __INLINE q15_t clip_q63_to_q15(
q63_t x)
{
return ((q31_t) (x >> 32) != ((q31_t) x >> 31)) ?
((0x7FFF ^ ((q15_t) (x >> 63)))) : (q15_t) (x >> 15);
}
/**
* @brief Clips Q31 to Q7 values.
*/
static __INLINE q7_t clip_q31_to_q7(
q31_t x)
{
return ((q31_t) (x >> 24) != ((q31_t) x >> 23)) ?
((0x7F ^ ((q7_t) (x >> 31)))) : (q7_t) x;
}
/**
* @brief Clips Q31 to Q15 values.
*/
static __INLINE q15_t clip_q31_to_q15(
q31_t x)
{
return ((q31_t) (x >> 16) != ((q31_t) x >> 15)) ?
((0x7FFF ^ ((q15_t) (x >> 31)))) : (q15_t) x;
}
/**
* @brief Multiplies 32 X 64 and returns 32 bit result in 2.30 format.
*/
static __INLINE q63_t mult32x64(
q63_t x,
q31_t y)
{
return ((((q63_t) (x & 0x00000000FFFFFFFF) * y) >> 32) +
(((q63_t) (x >> 32) * y)));
}
#if defined (ARM_MATH_CM0_FAMILY) && defined ( __CC_ARM )
#define __CLZ __clz
#endif
#if defined (ARM_MATH_CM0_FAMILY) && ((defined (__ICCARM__)) ||(defined (__GNUC__)) || defined (__TASKING__) )
static __INLINE uint32_t __CLZ(
q31_t data);
static __INLINE uint32_t __CLZ(
q31_t data)
{
uint32_t count = 0;
uint32_t mask = 0x80000000;
while((data & mask) == 0)
{
count += 1u;
mask = mask >> 1u;
}
return (count);
}
#endif
/**
* @brief Function to Calculates 1/in (reciprocal) value of Q31 Data type.
*/
static __INLINE uint32_t arm_recip_q31(
q31_t in,
q31_t * dst,
q31_t * pRecipTable)
{
uint32_t out, tempVal;
uint32_t index, i;
uint32_t signBits;
if(in > 0)
{
signBits = __CLZ(in) - 1;
}
else
{
signBits = __CLZ(-in) - 1;
}
/* Convert input sample to 1.31 format */
in = in << signBits;
/* calculation of index for initial approximated Val */
index = (uint32_t) (in >> 24u);
index = (index & INDEX_MASK);
/* 1.31 with exp 1 */
out = pRecipTable[index];
/* calculation of reciprocal value */
/* running approximation for two iterations */
for (i = 0u; i < 2u; i++)
{
tempVal = (q31_t) (((q63_t) in * out) >> 31u);
tempVal = 0x7FFFFFFF - tempVal;
/* 1.31 with exp 1 */
//out = (q31_t) (((q63_t) out * tempVal) >> 30u);
out = (q31_t) clip_q63_to_q31(((q63_t) out * tempVal) >> 30u);
}
/* write output */
*dst = out;
/* return num of signbits of out = 1/in value */
return (signBits + 1u);
}
/**
* @brief Function to Calculates 1/in (reciprocal) value of Q15 Data type.
*/
static __INLINE uint32_t arm_recip_q15(
q15_t in,
q15_t * dst,
q15_t * pRecipTable)
{
uint32_t out = 0, tempVal = 0;
uint32_t index = 0, i = 0;
uint32_t signBits = 0;
if(in > 0)
{
signBits = __CLZ(in) - 17;
}
else
{
signBits = __CLZ(-in) - 17;
}
/* Convert input sample to 1.15 format */
in = in << signBits;
/* calculation of index for initial approximated Val */
index = in >> 8;
index = (index & INDEX_MASK);
/* 1.15 with exp 1 */
out = pRecipTable[index];
/* calculation of reciprocal value */
/* running approximation for two iterations */
for (i = 0; i < 2; i++)
{
tempVal = (q15_t) (((q31_t) in * out) >> 15);
tempVal = 0x7FFF - tempVal;
/* 1.15 with exp 1 */
out = (q15_t) (((q31_t) out * tempVal) >> 14);
}
/* write output */
*dst = out;
/* return num of signbits of out = 1/in value */
return (signBits + 1);
}
/*
* @brief C custom defined intrinisic function for only M0 processors
*/
#if defined(ARM_MATH_CM0_FAMILY)
static __INLINE q31_t __SSAT(
q31_t x,
uint32_t y)
{
int32_t posMax, negMin;
uint32_t i;
posMax = 1;
for (i = 0; i < (y - 1); i++)
{
posMax = posMax * 2;
}
if(x > 0)
{
posMax = (posMax - 1);
if(x > posMax)
{
x = posMax;
}
}
else
{
negMin = -posMax;
if(x < negMin)
{
x = negMin;
}
}
return (x);
}
#endif /* end of ARM_MATH_CM0_FAMILY */
/*
* @brief C custom defined intrinsic function for M3 and M0 processors
*/
#if defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY)
/*
* @brief C custom defined QADD8 for M3 and M0 processors
*/
static __INLINE q31_t __QADD8(
q31_t x,
q31_t y)
{
q31_t sum;
q7_t r, s, t, u;
r = (q7_t) x;
s = (q7_t) y;
r = __SSAT((q31_t) (r + s), 8);
s = __SSAT(((q31_t) (((x << 16) >> 24) + ((y << 16) >> 24))), 8);
t = __SSAT(((q31_t) (((x << 8) >> 24) + ((y << 8) >> 24))), 8);
u = __SSAT(((q31_t) ((x >> 24) + (y >> 24))), 8);
sum =
(((q31_t) u << 24) & 0xFF000000) | (((q31_t) t << 16) & 0x00FF0000) |
(((q31_t) s << 8) & 0x0000FF00) | (r & 0x000000FF);
return sum;
}
/*
* @brief C custom defined QSUB8 for M3 and M0 processors
*/
static __INLINE q31_t __QSUB8(
q31_t x,
q31_t y)
{
q31_t sum;
q31_t r, s, t, u;
r = (q7_t) x;
s = (q7_t) y;
r = __SSAT((r - s), 8);
s = __SSAT(((q31_t) (((x << 16) >> 24) - ((y << 16) >> 24))), 8) << 8;
t = __SSAT(((q31_t) (((x << 8) >> 24) - ((y << 8) >> 24))), 8) << 16;
u = __SSAT(((q31_t) ((x >> 24) - (y >> 24))), 8) << 24;
sum =
(u & 0xFF000000) | (t & 0x00FF0000) | (s & 0x0000FF00) | (r &
0x000000FF);
return sum;
}
/*
* @brief C custom defined QADD16 for M3 and M0 processors
*/
/*
* @brief C custom defined QADD16 for M3 and M0 processors
*/
static __INLINE q31_t __QADD16(
q31_t x,
q31_t y)
{
q31_t sum;
q31_t r, s;
r = (q15_t) x;
s = (q15_t) y;
r = __SSAT(r + s, 16);
s = __SSAT(((q31_t) ((x >> 16) + (y >> 16))), 16) << 16;
sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
return sum;
}
/*
* @brief C custom defined SHADD16 for M3 and M0 processors
*/
static __INLINE q31_t __SHADD16(
q31_t x,
q31_t y)
{
q31_t sum;
q31_t r, s;
r = (q15_t) x;
s = (q15_t) y;
r = ((r >> 1) + (s >> 1));
s = ((q31_t) ((x >> 17) + (y >> 17))) << 16;
sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
return sum;
}
/*
* @brief C custom defined QSUB16 for M3 and M0 processors
*/
static __INLINE q31_t __QSUB16(
q31_t x,
q31_t y)
{
q31_t sum;
q31_t r, s;
r = (q15_t) x;
s = (q15_t) y;
r = __SSAT(r - s, 16);
s = __SSAT(((q31_t) ((x >> 16) - (y >> 16))), 16) << 16;
sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
return sum;
}
/*
* @brief C custom defined SHSUB16 for M3 and M0 processors
*/
static __INLINE q31_t __SHSUB16(
q31_t x,
q31_t y)
{
q31_t diff;
q31_t r, s;
r = (q15_t) x;
s = (q15_t) y;
r = ((r >> 1) - (s >> 1));
s = (((x >> 17) - (y >> 17)) << 16);
diff = (s & 0xFFFF0000) | (r & 0x0000FFFF);
return diff;
}
/*
* @brief C custom defined QASX for M3 and M0 processors
*/
static __INLINE q31_t __QASX(
q31_t x,
q31_t y)
{
q31_t sum = 0;
sum =
((sum +
clip_q31_to_q15((q31_t) ((q15_t) (x >> 16) + (q15_t) y))) << 16) +
clip_q31_to_q15((q31_t) ((q15_t) x - (q15_t) (y >> 16)));
return sum;
}
/*
* @brief C custom defined SHASX for M3 and M0 processors
*/
static __INLINE q31_t __SHASX(
q31_t x,
q31_t y)
{
q31_t sum;
q31_t r, s;
r = (q15_t) x;
s = (q15_t) y;
r = ((r >> 1) - (y >> 17));
s = (((x >> 17) + (s >> 1)) << 16);
sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
return sum;
}
/*
* @brief C custom defined QSAX for M3 and M0 processors
*/
static __INLINE q31_t __QSAX(
q31_t x,
q31_t y)
{
q31_t sum = 0;
sum =
((sum +
clip_q31_to_q15((q31_t) ((q15_t) (x >> 16) - (q15_t) y))) << 16) +
clip_q31_to_q15((q31_t) ((q15_t) x + (q15_t) (y >> 16)));
return sum;
}
/*
* @brief C custom defined SHSAX for M3 and M0 processors
*/
static __INLINE q31_t __SHSAX(
q31_t x,
q31_t y)
{
q31_t sum;
q31_t r, s;
r = (q15_t) x;
s = (q15_t) y;
r = ((r >> 1) + (y >> 17));
s = (((x >> 17) - (s >> 1)) << 16);
sum = (s & 0xFFFF0000) | (r & 0x0000FFFF);
return sum;
}
/*
* @brief C custom defined SMUSDX for M3 and M0 processors
*/
static __INLINE q31_t __SMUSDX(
q31_t x,
q31_t y)
{
return ((q31_t) (((q15_t) x * (q15_t) (y >> 16)) -
((q15_t) (x >> 16) * (q15_t) y)));
}
/*
* @brief C custom defined SMUADX for M3 and M0 processors
*/
static __INLINE q31_t __SMUADX(
q31_t x,
q31_t y)
{
return ((q31_t) (((q15_t) x * (q15_t) (y >> 16)) +
((q15_t) (x >> 16) * (q15_t) y)));
}
/*
* @brief C custom defined QADD for M3 and M0 processors
*/
static __INLINE q31_t __QADD(
q31_t x,
q31_t y)
{
return clip_q63_to_q31((q63_t) x + y);
}
/*
* @brief C custom defined QSUB for M3 and M0 processors
*/
static __INLINE q31_t __QSUB(
q31_t x,
q31_t y)
{
return clip_q63_to_q31((q63_t) x - y);
}
/*
* @brief C custom defined SMLAD for M3 and M0 processors
*/
static __INLINE q31_t __SMLAD(
q31_t x,
q31_t y,
q31_t sum)
{
return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) +
((q15_t) x * (q15_t) y));
}
/*
* @brief C custom defined SMLADX for M3 and M0 processors
*/
static __INLINE q31_t __SMLADX(
q31_t x,
q31_t y,
q31_t sum)
{
return (sum + ((q15_t) (x >> 16) * (q15_t) (y)) +
((q15_t) x * (q15_t) (y >> 16)));
}
/*
* @brief C custom defined SMLSDX for M3 and M0 processors
*/
static __INLINE q31_t __SMLSDX(
q31_t x,
q31_t y,
q31_t sum)
{
return (sum - ((q15_t) (x >> 16) * (q15_t) (y)) +
((q15_t) x * (q15_t) (y >> 16)));
}
/*
* @brief C custom defined SMLALD for M3 and M0 processors
*/
static __INLINE q63_t __SMLALD(
q31_t x,
q31_t y,
q63_t sum)
{
return (sum + ((q15_t) (x >> 16) * (q15_t) (y >> 16)) +
((q15_t) x * (q15_t) y));
}
/*
* @brief C custom defined SMLALDX for M3 and M0 processors
*/
static __INLINE q63_t __SMLALDX(
q31_t x,
q31_t y,
q63_t sum)
{
return (sum + ((q15_t) (x >> 16) * (q15_t) y)) +
((q15_t) x * (q15_t) (y >> 16));
}
/*
* @brief C custom defined SMUAD for M3 and M0 processors
*/
static __INLINE q31_t __SMUAD(
q31_t x,
q31_t y)
{
return (((x >> 16) * (y >> 16)) +
(((x << 16) >> 16) * ((y << 16) >> 16)));
}
/*
* @brief C custom defined SMUSD for M3 and M0 processors
*/
static __INLINE q31_t __SMUSD(
q31_t x,
q31_t y)
{
return (-((x >> 16) * (y >> 16)) +
(((x << 16) >> 16) * ((y << 16) >> 16)));
}
/*
* @brief C custom defined SXTB16 for M3 and M0 processors
*/
static __INLINE q31_t __SXTB16(
q31_t x)
{
return ((((x << 24) >> 24) & 0x0000FFFF) |
(((x << 8) >> 8) & 0xFFFF0000));
}
#endif /* defined (ARM_MATH_CM3) || defined (ARM_MATH_CM0_FAMILY) */
/**
* @brief Instance structure for the Q7 FIR filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of filter coefficients in the filter. */
q7_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/
} arm_fir_instance_q7;
/**
* @brief Instance structure for the Q15 FIR filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of filter coefficients in the filter. */
q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/
} arm_fir_instance_q15;
/**
* @brief Instance structure for the Q31 FIR filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of filter coefficients in the filter. */
q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */
} arm_fir_instance_q31;
/**
* @brief Instance structure for the floating-point FIR filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of filter coefficients in the filter. */
float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */
} arm_fir_instance_f32;
/**
* @brief Processing function for the Q7 FIR filter.
* @param[in] *S points to an instance of the Q7 FIR filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_fir_q7(
const arm_fir_instance_q7 * S,
q7_t * pSrc,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q7 FIR filter.
* @param[in,out] *S points to an instance of the Q7 FIR structure.
* @param[in] numTaps Number of filter coefficients in the filter.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of samples that are processed.
* @return none
*/
void arm_fir_init_q7(
arm_fir_instance_q7 * S,
uint16_t numTaps,
q7_t * pCoeffs,
q7_t * pState,
uint32_t blockSize);
/**
* @brief Processing function for the Q15 FIR filter.
* @param[in] *S points to an instance of the Q15 FIR structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_fir_q15(
const arm_fir_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Processing function for the fast Q15 FIR filter for Cortex-M3 and Cortex-M4.
* @param[in] *S points to an instance of the Q15 FIR filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_fir_fast_q15(
const arm_fir_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q15 FIR filter.
* @param[in,out] *S points to an instance of the Q15 FIR filter structure.
* @param[in] numTaps Number of filter coefficients in the filter. Must be even and greater than or equal to 4.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of samples that are processed at a time.
* @return The function returns ARM_MATH_SUCCESS if initialization was successful or ARM_MATH_ARGUMENT_ERROR if
* numTaps is not a supported value.
*/
arm_status arm_fir_init_q15(
arm_fir_instance_q15 * S,
uint16_t numTaps,
q15_t * pCoeffs,
q15_t * pState,
uint32_t blockSize);
/**
* @brief Processing function for the Q31 FIR filter.
* @param[in] *S points to an instance of the Q31 FIR filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_fir_q31(
const arm_fir_instance_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Processing function for the fast Q31 FIR filter for Cortex-M3 and Cortex-M4.
* @param[in] *S points to an instance of the Q31 FIR structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_fir_fast_q31(
const arm_fir_instance_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q31 FIR filter.
* @param[in,out] *S points to an instance of the Q31 FIR structure.
* @param[in] numTaps Number of filter coefficients in the filter.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of samples that are processed at a time.
* @return none.
*/
void arm_fir_init_q31(
arm_fir_instance_q31 * S,
uint16_t numTaps,
q31_t * pCoeffs,
q31_t * pState,
uint32_t blockSize);
/**
* @brief Processing function for the floating-point FIR filter.
* @param[in] *S points to an instance of the floating-point FIR structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_fir_f32(
const arm_fir_instance_f32 * S,
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the floating-point FIR filter.
* @param[in,out] *S points to an instance of the floating-point FIR filter structure.
* @param[in] numTaps Number of filter coefficients in the filter.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of samples that are processed at a time.
* @return none.
*/
void arm_fir_init_f32(
arm_fir_instance_f32 * S,
uint16_t numTaps,
float32_t * pCoeffs,
float32_t * pState,
uint32_t blockSize);
/**
* @brief Instance structure for the Q15 Biquad cascade filter.
*/
typedef struct
{
int8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */
q15_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */
q15_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */
int8_t postShift; /**< Additional shift, in bits, applied to each output sample. */
} arm_biquad_casd_df1_inst_q15;
/**
* @brief Instance structure for the Q31 Biquad cascade filter.
*/
typedef struct
{
uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */
q31_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */
q31_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */
uint8_t postShift; /**< Additional shift, in bits, applied to each output sample. */
} arm_biquad_casd_df1_inst_q31;
/**
* @brief Instance structure for the floating-point Biquad cascade filter.
*/
typedef struct
{
uint32_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */
float32_t *pState; /**< Points to the array of state coefficients. The array is of length 4*numStages. */
float32_t *pCoeffs; /**< Points to the array of coefficients. The array is of length 5*numStages. */
} arm_biquad_casd_df1_inst_f32;
/**
* @brief Processing function for the Q15 Biquad cascade filter.
* @param[in] *S points to an instance of the Q15 Biquad cascade structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_biquad_cascade_df1_q15(
const arm_biquad_casd_df1_inst_q15 * S,
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q15 Biquad cascade filter.
* @param[in,out] *S points to an instance of the Q15 Biquad cascade structure.
* @param[in] numStages number of 2nd order stages in the filter.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format
* @return none
*/
void arm_biquad_cascade_df1_init_q15(
arm_biquad_casd_df1_inst_q15 * S,
uint8_t numStages,
q15_t * pCoeffs,
q15_t * pState,
int8_t postShift);
/**
* @brief Fast but less precise processing function for the Q15 Biquad cascade filter for Cortex-M3 and Cortex-M4.
* @param[in] *S points to an instance of the Q15 Biquad cascade structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_biquad_cascade_df1_fast_q15(
const arm_biquad_casd_df1_inst_q15 * S,
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Processing function for the Q31 Biquad cascade filter
* @param[in] *S points to an instance of the Q31 Biquad cascade structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_biquad_cascade_df1_q31(
const arm_biquad_casd_df1_inst_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Fast but less precise processing function for the Q31 Biquad cascade filter for Cortex-M3 and Cortex-M4.
* @param[in] *S points to an instance of the Q31 Biquad cascade structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_biquad_cascade_df1_fast_q31(
const arm_biquad_casd_df1_inst_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q31 Biquad cascade filter.
* @param[in,out] *S points to an instance of the Q31 Biquad cascade structure.
* @param[in] numStages number of 2nd order stages in the filter.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] postShift Shift to be applied to the output. Varies according to the coefficients format
* @return none
*/
void arm_biquad_cascade_df1_init_q31(
arm_biquad_casd_df1_inst_q31 * S,
uint8_t numStages,
q31_t * pCoeffs,
q31_t * pState,
int8_t postShift);
/**
* @brief Processing function for the floating-point Biquad cascade filter.
* @param[in] *S points to an instance of the floating-point Biquad cascade structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_biquad_cascade_df1_f32(
const arm_biquad_casd_df1_inst_f32 * S,
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the floating-point Biquad cascade filter.
* @param[in,out] *S points to an instance of the floating-point Biquad cascade structure.
* @param[in] numStages number of 2nd order stages in the filter.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @return none
*/
void arm_biquad_cascade_df1_init_f32(
arm_biquad_casd_df1_inst_f32 * S,
uint8_t numStages,
float32_t * pCoeffs,
float32_t * pState);
/**
* @brief Instance structure for the floating-point matrix structure.
*/
typedef struct
{
uint16_t numRows; /**< number of rows of the matrix. */
uint16_t numCols; /**< number of columns of the matrix. */
float32_t *pData; /**< points to the data of the matrix. */
} arm_matrix_instance_f32;
/**
* @brief Instance structure for the Q15 matrix structure.
*/
typedef struct
{
uint16_t numRows; /**< number of rows of the matrix. */
uint16_t numCols; /**< number of columns of the matrix. */
q15_t *pData; /**< points to the data of the matrix. */
} arm_matrix_instance_q15;
/**
* @brief Instance structure for the Q31 matrix structure.
*/
typedef struct
{
uint16_t numRows; /**< number of rows of the matrix. */
uint16_t numCols; /**< number of columns of the matrix. */
q31_t *pData; /**< points to the data of the matrix. */
} arm_matrix_instance_q31;
/**
* @brief Floating-point matrix addition.
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_add_f32(
const arm_matrix_instance_f32 * pSrcA,
const arm_matrix_instance_f32 * pSrcB,
arm_matrix_instance_f32 * pDst);
/**
* @brief Q15 matrix addition.
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_add_q15(
const arm_matrix_instance_q15 * pSrcA,
const arm_matrix_instance_q15 * pSrcB,
arm_matrix_instance_q15 * pDst);
/**
* @brief Q31 matrix addition.
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_add_q31(
const arm_matrix_instance_q31 * pSrcA,
const arm_matrix_instance_q31 * pSrcB,
arm_matrix_instance_q31 * pDst);
/**
* @brief Floating-point, complex, matrix multiplication.
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_cmplx_mult_f32(
const arm_matrix_instance_f32 * pSrcA,
const arm_matrix_instance_f32 * pSrcB,
arm_matrix_instance_f32 * pDst);
/**
* @brief Q15, complex, matrix multiplication.
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_cmplx_mult_q15(
const arm_matrix_instance_q15 * pSrcA,
const arm_matrix_instance_q15 * pSrcB,
arm_matrix_instance_q15 * pDst,
q15_t * pScratch);
/**
* @brief Q31, complex, matrix multiplication.
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_cmplx_mult_q31(
const arm_matrix_instance_q31 * pSrcA,
const arm_matrix_instance_q31 * pSrcB,
arm_matrix_instance_q31 * pDst);
/**
* @brief Floating-point matrix transpose.
* @param[in] *pSrc points to the input matrix
* @param[out] *pDst points to the output matrix
* @return The function returns either ARM_MATH_SIZE_MISMATCH
* or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_trans_f32(
const arm_matrix_instance_f32 * pSrc,
arm_matrix_instance_f32 * pDst);
/**
* @brief Q15 matrix transpose.
* @param[in] *pSrc points to the input matrix
* @param[out] *pDst points to the output matrix
* @return The function returns either ARM_MATH_SIZE_MISMATCH
* or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_trans_q15(
const arm_matrix_instance_q15 * pSrc,
arm_matrix_instance_q15 * pDst);
/**
* @brief Q31 matrix transpose.
* @param[in] *pSrc points to the input matrix
* @param[out] *pDst points to the output matrix
* @return The function returns either ARM_MATH_SIZE_MISMATCH
* or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_trans_q31(
const arm_matrix_instance_q31 * pSrc,
arm_matrix_instance_q31 * pDst);
/**
* @brief Floating-point matrix multiplication
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_mult_f32(
const arm_matrix_instance_f32 * pSrcA,
const arm_matrix_instance_f32 * pSrcB,
arm_matrix_instance_f32 * pDst);
/**
* @brief Q15 matrix multiplication
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @param[in] *pState points to the array for storing intermediate results
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_mult_q15(
const arm_matrix_instance_q15 * pSrcA,
const arm_matrix_instance_q15 * pSrcB,
arm_matrix_instance_q15 * pDst,
q15_t * pState);
/**
* @brief Q15 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @param[in] *pState points to the array for storing intermediate results
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_mult_fast_q15(
const arm_matrix_instance_q15 * pSrcA,
const arm_matrix_instance_q15 * pSrcB,
arm_matrix_instance_q15 * pDst,
q15_t * pState);
/**
* @brief Q31 matrix multiplication
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_mult_q31(
const arm_matrix_instance_q31 * pSrcA,
const arm_matrix_instance_q31 * pSrcB,
arm_matrix_instance_q31 * pDst);
/**
* @brief Q31 matrix multiplication (fast variant) for Cortex-M3 and Cortex-M4
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_mult_fast_q31(
const arm_matrix_instance_q31 * pSrcA,
const arm_matrix_instance_q31 * pSrcB,
arm_matrix_instance_q31 * pDst);
/**
* @brief Floating-point matrix subtraction
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_sub_f32(
const arm_matrix_instance_f32 * pSrcA,
const arm_matrix_instance_f32 * pSrcB,
arm_matrix_instance_f32 * pDst);
/**
* @brief Q15 matrix subtraction
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_sub_q15(
const arm_matrix_instance_q15 * pSrcA,
const arm_matrix_instance_q15 * pSrcB,
arm_matrix_instance_q15 * pDst);
/**
* @brief Q31 matrix subtraction
* @param[in] *pSrcA points to the first input matrix structure
* @param[in] *pSrcB points to the second input matrix structure
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_sub_q31(
const arm_matrix_instance_q31 * pSrcA,
const arm_matrix_instance_q31 * pSrcB,
arm_matrix_instance_q31 * pDst);
/**
* @brief Floating-point matrix scaling.
* @param[in] *pSrc points to the input matrix
* @param[in] scale scale factor
* @param[out] *pDst points to the output matrix
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_scale_f32(
const arm_matrix_instance_f32 * pSrc,
float32_t scale,
arm_matrix_instance_f32 * pDst);
/**
* @brief Q15 matrix scaling.
* @param[in] *pSrc points to input matrix
* @param[in] scaleFract fractional portion of the scale factor
* @param[in] shift number of bits to shift the result by
* @param[out] *pDst points to output matrix
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_scale_q15(
const arm_matrix_instance_q15 * pSrc,
q15_t scaleFract,
int32_t shift,
arm_matrix_instance_q15 * pDst);
/**
* @brief Q31 matrix scaling.
* @param[in] *pSrc points to input matrix
* @param[in] scaleFract fractional portion of the scale factor
* @param[in] shift number of bits to shift the result by
* @param[out] *pDst points to output matrix structure
* @return The function returns either
* ARM_MATH_SIZE_MISMATCH or ARM_MATH_SUCCESS based on the outcome of size checking.
*/
arm_status arm_mat_scale_q31(
const arm_matrix_instance_q31 * pSrc,
q31_t scaleFract,
int32_t shift,
arm_matrix_instance_q31 * pDst);
/**
* @brief Q31 matrix initialization.
* @param[in,out] *S points to an instance of the floating-point matrix structure.
* @param[in] nRows number of rows in the matrix.
* @param[in] nColumns number of columns in the matrix.
* @param[in] *pData points to the matrix data array.
* @return none
*/
void arm_mat_init_q31(
arm_matrix_instance_q31 * S,
uint16_t nRows,
uint16_t nColumns,
q31_t * pData);
/**
* @brief Q15 matrix initialization.
* @param[in,out] *S points to an instance of the floating-point matrix structure.
* @param[in] nRows number of rows in the matrix.
* @param[in] nColumns number of columns in the matrix.
* @param[in] *pData points to the matrix data array.
* @return none
*/
void arm_mat_init_q15(
arm_matrix_instance_q15 * S,
uint16_t nRows,
uint16_t nColumns,
q15_t * pData);
/**
* @brief Floating-point matrix initialization.
* @param[in,out] *S points to an instance of the floating-point matrix structure.
* @param[in] nRows number of rows in the matrix.
* @param[in] nColumns number of columns in the matrix.
* @param[in] *pData points to the matrix data array.
* @return none
*/
void arm_mat_init_f32(
arm_matrix_instance_f32 * S,
uint16_t nRows,
uint16_t nColumns,
float32_t * pData);
/**
* @brief Instance structure for the Q15 PID Control.
*/
typedef struct
{
q15_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */
#ifdef ARM_MATH_CM0_FAMILY
q15_t A1;
q15_t A2;
#else
q31_t A1; /**< The derived gain A1 = -Kp - 2Kd | Kd.*/
#endif
q15_t state[3]; /**< The state array of length 3. */
q15_t Kp; /**< The proportional gain. */
q15_t Ki; /**< The integral gain. */
q15_t Kd; /**< The derivative gain. */
} arm_pid_instance_q15;
/**
* @brief Instance structure for the Q31 PID Control.
*/
typedef struct
{
q31_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */
q31_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */
q31_t A2; /**< The derived gain, A2 = Kd . */
q31_t state[3]; /**< The state array of length 3. */
q31_t Kp; /**< The proportional gain. */
q31_t Ki; /**< The integral gain. */
q31_t Kd; /**< The derivative gain. */
} arm_pid_instance_q31;
/**
* @brief Instance structure for the floating-point PID Control.
*/
typedef struct
{
float32_t A0; /**< The derived gain, A0 = Kp + Ki + Kd . */
float32_t A1; /**< The derived gain, A1 = -Kp - 2Kd. */
float32_t A2; /**< The derived gain, A2 = Kd . */
float32_t state[3]; /**< The state array of length 3. */
float32_t Kp; /**< The proportional gain. */
float32_t Ki; /**< The integral gain. */
float32_t Kd; /**< The derivative gain. */
} arm_pid_instance_f32;
/**
* @brief Initialization function for the floating-point PID Control.
* @param[in,out] *S points to an instance of the PID structure.
* @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state.
* @return none.
*/
void arm_pid_init_f32(
arm_pid_instance_f32 * S,
int32_t resetStateFlag);
/**
* @brief Reset function for the floating-point PID Control.
* @param[in,out] *S is an instance of the floating-point PID Control structure
* @return none
*/
void arm_pid_reset_f32(
arm_pid_instance_f32 * S);
/**
* @brief Initialization function for the Q31 PID Control.
* @param[in,out] *S points to an instance of the Q15 PID structure.
* @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state.
* @return none.
*/
void arm_pid_init_q31(
arm_pid_instance_q31 * S,
int32_t resetStateFlag);
/**
* @brief Reset function for the Q31 PID Control.
* @param[in,out] *S points to an instance of the Q31 PID Control structure
* @return none
*/
void arm_pid_reset_q31(
arm_pid_instance_q31 * S);
/**
* @brief Initialization function for the Q15 PID Control.
* @param[in,out] *S points to an instance of the Q15 PID structure.
* @param[in] resetStateFlag flag to reset the state. 0 = no change in state 1 = reset the state.
* @return none.
*/
void arm_pid_init_q15(
arm_pid_instance_q15 * S,
int32_t resetStateFlag);
/**
* @brief Reset function for the Q15 PID Control.
* @param[in,out] *S points to an instance of the q15 PID Control structure
* @return none
*/
void arm_pid_reset_q15(
arm_pid_instance_q15 * S);
/**
* @brief Instance structure for the floating-point Linear Interpolate function.
*/
typedef struct
{
uint32_t nValues; /**< nValues */
float32_t x1; /**< x1 */
float32_t xSpacing; /**< xSpacing */
float32_t *pYData; /**< pointer to the table of Y values */
} arm_linear_interp_instance_f32;
/**
* @brief Instance structure for the floating-point bilinear interpolation function.
*/
typedef struct
{
uint16_t numRows; /**< number of rows in the data table. */
uint16_t numCols; /**< number of columns in the data table. */
float32_t *pData; /**< points to the data table. */
} arm_bilinear_interp_instance_f32;
/**
* @brief Instance structure for the Q31 bilinear interpolation function.
*/
typedef struct
{
uint16_t numRows; /**< number of rows in the data table. */
uint16_t numCols; /**< number of columns in the data table. */
q31_t *pData; /**< points to the data table. */
} arm_bilinear_interp_instance_q31;
/**
* @brief Instance structure for the Q15 bilinear interpolation function.
*/
typedef struct
{
uint16_t numRows; /**< number of rows in the data table. */
uint16_t numCols; /**< number of columns in the data table. */
q15_t *pData; /**< points to the data table. */
} arm_bilinear_interp_instance_q15;
/**
* @brief Instance structure for the Q15 bilinear interpolation function.
*/
typedef struct
{
uint16_t numRows; /**< number of rows in the data table. */
uint16_t numCols; /**< number of columns in the data table. */
q7_t *pData; /**< points to the data table. */
} arm_bilinear_interp_instance_q7;
/**
* @brief Q7 vector multiplication.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_mult_q7(
q7_t * pSrcA,
q7_t * pSrcB,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Q15 vector multiplication.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_mult_q15(
q15_t * pSrcA,
q15_t * pSrcB,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Q31 vector multiplication.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_mult_q31(
q31_t * pSrcA,
q31_t * pSrcB,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Floating-point vector multiplication.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_mult_f32(
float32_t * pSrcA,
float32_t * pSrcB,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Instance structure for the Q15 CFFT/CIFFT function.
*/
typedef struct
{
uint16_t fftLen; /**< length of the FFT. */
uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
q15_t *pTwiddle; /**< points to the Sin twiddle factor table. */
uint16_t *pBitRevTable; /**< points to the bit reversal table. */
uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
} arm_cfft_radix2_instance_q15;
arm_status arm_cfft_radix2_init_q15(
arm_cfft_radix2_instance_q15 * S,
uint16_t fftLen,
uint8_t ifftFlag,
uint8_t bitReverseFlag);
void arm_cfft_radix2_q15(
const arm_cfft_radix2_instance_q15 * S,
q15_t * pSrc);
/**
* @brief Instance structure for the Q15 CFFT/CIFFT function.
*/
typedef struct
{
uint16_t fftLen; /**< length of the FFT. */
uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
q15_t *pTwiddle; /**< points to the twiddle factor table. */
uint16_t *pBitRevTable; /**< points to the bit reversal table. */
uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
} arm_cfft_radix4_instance_q15;
arm_status arm_cfft_radix4_init_q15(
arm_cfft_radix4_instance_q15 * S,
uint16_t fftLen,
uint8_t ifftFlag,
uint8_t bitReverseFlag);
void arm_cfft_radix4_q15(
const arm_cfft_radix4_instance_q15 * S,
q15_t * pSrc);
/**
* @brief Instance structure for the Radix-2 Q31 CFFT/CIFFT function.
*/
typedef struct
{
uint16_t fftLen; /**< length of the FFT. */
uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
q31_t *pTwiddle; /**< points to the Twiddle factor table. */
uint16_t *pBitRevTable; /**< points to the bit reversal table. */
uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
} arm_cfft_radix2_instance_q31;
arm_status arm_cfft_radix2_init_q31(
arm_cfft_radix2_instance_q31 * S,
uint16_t fftLen,
uint8_t ifftFlag,
uint8_t bitReverseFlag);
void arm_cfft_radix2_q31(
const arm_cfft_radix2_instance_q31 * S,
q31_t * pSrc);
/**
* @brief Instance structure for the Q31 CFFT/CIFFT function.
*/
typedef struct
{
uint16_t fftLen; /**< length of the FFT. */
uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
q31_t *pTwiddle; /**< points to the twiddle factor table. */
uint16_t *pBitRevTable; /**< points to the bit reversal table. */
uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
} arm_cfft_radix4_instance_q31;
void arm_cfft_radix4_q31(
const arm_cfft_radix4_instance_q31 * S,
q31_t * pSrc);
arm_status arm_cfft_radix4_init_q31(
arm_cfft_radix4_instance_q31 * S,
uint16_t fftLen,
uint8_t ifftFlag,
uint8_t bitReverseFlag);
/**
* @brief Instance structure for the floating-point CFFT/CIFFT function.
*/
typedef struct
{
uint16_t fftLen; /**< length of the FFT. */
uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
float32_t *pTwiddle; /**< points to the Twiddle factor table. */
uint16_t *pBitRevTable; /**< points to the bit reversal table. */
uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
float32_t onebyfftLen; /**< value of 1/fftLen. */
} arm_cfft_radix2_instance_f32;
/* Deprecated */
arm_status arm_cfft_radix2_init_f32(
arm_cfft_radix2_instance_f32 * S,
uint16_t fftLen,
uint8_t ifftFlag,
uint8_t bitReverseFlag);
/* Deprecated */
void arm_cfft_radix2_f32(
const arm_cfft_radix2_instance_f32 * S,
float32_t * pSrc);
/**
* @brief Instance structure for the floating-point CFFT/CIFFT function.
*/
typedef struct
{
uint16_t fftLen; /**< length of the FFT. */
uint8_t ifftFlag; /**< flag that selects forward (ifftFlag=0) or inverse (ifftFlag=1) transform. */
uint8_t bitReverseFlag; /**< flag that enables (bitReverseFlag=1) or disables (bitReverseFlag=0) bit reversal of output. */
float32_t *pTwiddle; /**< points to the Twiddle factor table. */
uint16_t *pBitRevTable; /**< points to the bit reversal table. */
uint16_t twidCoefModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
uint16_t bitRevFactor; /**< bit reversal modifier that supports different size FFTs with the same bit reversal table. */
float32_t onebyfftLen; /**< value of 1/fftLen. */
} arm_cfft_radix4_instance_f32;
/* Deprecated */
arm_status arm_cfft_radix4_init_f32(
arm_cfft_radix4_instance_f32 * S,
uint16_t fftLen,
uint8_t ifftFlag,
uint8_t bitReverseFlag);
/* Deprecated */
void arm_cfft_radix4_f32(
const arm_cfft_radix4_instance_f32 * S,
float32_t * pSrc);
/**
* @brief Instance structure for the floating-point CFFT/CIFFT function.
*/
typedef struct
{
uint16_t fftLen; /**< length of the FFT. */
const float32_t *pTwiddle; /**< points to the Twiddle factor table. */
const uint16_t *pBitRevTable; /**< points to the bit reversal table. */
uint16_t bitRevLength; /**< bit reversal table length. */
} arm_cfft_instance_f32;
void arm_cfft_f32(
const arm_cfft_instance_f32 * S,
float32_t * p1,
uint8_t ifftFlag,
uint8_t bitReverseFlag);
/**
* @brief Instance structure for the Q15 RFFT/RIFFT function.
*/
typedef struct
{
uint32_t fftLenReal; /**< length of the real FFT. */
uint32_t fftLenBy2; /**< length of the complex FFT. */
uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */
uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */
uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
q15_t *pTwiddleAReal; /**< points to the real twiddle factor table. */
q15_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */
arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */
} arm_rfft_instance_q15;
arm_status arm_rfft_init_q15(
arm_rfft_instance_q15 * S,
arm_cfft_radix4_instance_q15 * S_CFFT,
uint32_t fftLenReal,
uint32_t ifftFlagR,
uint32_t bitReverseFlag);
void arm_rfft_q15(
const arm_rfft_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst);
/**
* @brief Instance structure for the Q31 RFFT/RIFFT function.
*/
typedef struct
{
uint32_t fftLenReal; /**< length of the real FFT. */
uint32_t fftLenBy2; /**< length of the complex FFT. */
uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */
uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */
uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
q31_t *pTwiddleAReal; /**< points to the real twiddle factor table. */
q31_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */
arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */
} arm_rfft_instance_q31;
arm_status arm_rfft_init_q31(
arm_rfft_instance_q31 * S,
arm_cfft_radix4_instance_q31 * S_CFFT,
uint32_t fftLenReal,
uint32_t ifftFlagR,
uint32_t bitReverseFlag);
void arm_rfft_q31(
const arm_rfft_instance_q31 * S,
q31_t * pSrc,
q31_t * pDst);
/**
* @brief Instance structure for the floating-point RFFT/RIFFT function.
*/
typedef struct
{
uint32_t fftLenReal; /**< length of the real FFT. */
uint16_t fftLenBy2; /**< length of the complex FFT. */
uint8_t ifftFlagR; /**< flag that selects forward (ifftFlagR=0) or inverse (ifftFlagR=1) transform. */
uint8_t bitReverseFlagR; /**< flag that enables (bitReverseFlagR=1) or disables (bitReverseFlagR=0) bit reversal of output. */
uint32_t twidCoefRModifier; /**< twiddle coefficient modifier that supports different size FFTs with the same twiddle factor table. */
float32_t *pTwiddleAReal; /**< points to the real twiddle factor table. */
float32_t *pTwiddleBReal; /**< points to the imag twiddle factor table. */
arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */
} arm_rfft_instance_f32;
arm_status arm_rfft_init_f32(
arm_rfft_instance_f32 * S,
arm_cfft_radix4_instance_f32 * S_CFFT,
uint32_t fftLenReal,
uint32_t ifftFlagR,
uint32_t bitReverseFlag);
void arm_rfft_f32(
const arm_rfft_instance_f32 * S,
float32_t * pSrc,
float32_t * pDst);
/**
* @brief Instance structure for the floating-point RFFT/RIFFT function.
*/
typedef struct
{
arm_cfft_instance_f32 Sint; /**< Internal CFFT structure. */
uint16_t fftLenRFFT; /**< length of the real sequence */
float32_t * pTwiddleRFFT; /**< Twiddle factors real stage */
} arm_rfft_fast_instance_f32 ;
arm_status arm_rfft_fast_init_f32 (
arm_rfft_fast_instance_f32 * S,
uint16_t fftLen);
void arm_rfft_fast_f32(
arm_rfft_fast_instance_f32 * S,
float32_t * p, float32_t * pOut,
uint8_t ifftFlag);
/**
* @brief Instance structure for the floating-point DCT4/IDCT4 function.
*/
typedef struct
{
uint16_t N; /**< length of the DCT4. */
uint16_t Nby2; /**< half of the length of the DCT4. */
float32_t normalize; /**< normalizing factor. */
float32_t *pTwiddle; /**< points to the twiddle factor table. */
float32_t *pCosFactor; /**< points to the cosFactor table. */
arm_rfft_instance_f32 *pRfft; /**< points to the real FFT instance. */
arm_cfft_radix4_instance_f32 *pCfft; /**< points to the complex FFT instance. */
} arm_dct4_instance_f32;
/**
* @brief Initialization function for the floating-point DCT4/IDCT4.
* @param[in,out] *S points to an instance of floating-point DCT4/IDCT4 structure.
* @param[in] *S_RFFT points to an instance of floating-point RFFT/RIFFT structure.
* @param[in] *S_CFFT points to an instance of floating-point CFFT/CIFFT structure.
* @param[in] N length of the DCT4.
* @param[in] Nby2 half of the length of the DCT4.
* @param[in] normalize normalizing factor.
* @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if fftLenReal is not a supported transform length.
*/
arm_status arm_dct4_init_f32(
arm_dct4_instance_f32 * S,
arm_rfft_instance_f32 * S_RFFT,
arm_cfft_radix4_instance_f32 * S_CFFT,
uint16_t N,
uint16_t Nby2,
float32_t normalize);
/**
* @brief Processing function for the floating-point DCT4/IDCT4.
* @param[in] *S points to an instance of the floating-point DCT4/IDCT4 structure.
* @param[in] *pState points to state buffer.
* @param[in,out] *pInlineBuffer points to the in-place input and output buffer.
* @return none.
*/
void arm_dct4_f32(
const arm_dct4_instance_f32 * S,
float32_t * pState,
float32_t * pInlineBuffer);
/**
* @brief Instance structure for the Q31 DCT4/IDCT4 function.
*/
typedef struct
{
uint16_t N; /**< length of the DCT4. */
uint16_t Nby2; /**< half of the length of the DCT4. */
q31_t normalize; /**< normalizing factor. */
q31_t *pTwiddle; /**< points to the twiddle factor table. */
q31_t *pCosFactor; /**< points to the cosFactor table. */
arm_rfft_instance_q31 *pRfft; /**< points to the real FFT instance. */
arm_cfft_radix4_instance_q31 *pCfft; /**< points to the complex FFT instance. */
} arm_dct4_instance_q31;
/**
* @brief Initialization function for the Q31 DCT4/IDCT4.
* @param[in,out] *S points to an instance of Q31 DCT4/IDCT4 structure.
* @param[in] *S_RFFT points to an instance of Q31 RFFT/RIFFT structure
* @param[in] *S_CFFT points to an instance of Q31 CFFT/CIFFT structure
* @param[in] N length of the DCT4.
* @param[in] Nby2 half of the length of the DCT4.
* @param[in] normalize normalizing factor.
* @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length.
*/
arm_status arm_dct4_init_q31(
arm_dct4_instance_q31 * S,
arm_rfft_instance_q31 * S_RFFT,
arm_cfft_radix4_instance_q31 * S_CFFT,
uint16_t N,
uint16_t Nby2,
q31_t normalize);
/**
* @brief Processing function for the Q31 DCT4/IDCT4.
* @param[in] *S points to an instance of the Q31 DCT4 structure.
* @param[in] *pState points to state buffer.
* @param[in,out] *pInlineBuffer points to the in-place input and output buffer.
* @return none.
*/
void arm_dct4_q31(
const arm_dct4_instance_q31 * S,
q31_t * pState,
q31_t * pInlineBuffer);
/**
* @brief Instance structure for the Q15 DCT4/IDCT4 function.
*/
typedef struct
{
uint16_t N; /**< length of the DCT4. */
uint16_t Nby2; /**< half of the length of the DCT4. */
q15_t normalize; /**< normalizing factor. */
q15_t *pTwiddle; /**< points to the twiddle factor table. */
q15_t *pCosFactor; /**< points to the cosFactor table. */
arm_rfft_instance_q15 *pRfft; /**< points to the real FFT instance. */
arm_cfft_radix4_instance_q15 *pCfft; /**< points to the complex FFT instance. */
} arm_dct4_instance_q15;
/**
* @brief Initialization function for the Q15 DCT4/IDCT4.
* @param[in,out] *S points to an instance of Q15 DCT4/IDCT4 structure.
* @param[in] *S_RFFT points to an instance of Q15 RFFT/RIFFT structure.
* @param[in] *S_CFFT points to an instance of Q15 CFFT/CIFFT structure.
* @param[in] N length of the DCT4.
* @param[in] Nby2 half of the length of the DCT4.
* @param[in] normalize normalizing factor.
* @return arm_status function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_ARGUMENT_ERROR if N is not a supported transform length.
*/
arm_status arm_dct4_init_q15(
arm_dct4_instance_q15 * S,
arm_rfft_instance_q15 * S_RFFT,
arm_cfft_radix4_instance_q15 * S_CFFT,
uint16_t N,
uint16_t Nby2,
q15_t normalize);
/**
* @brief Processing function for the Q15 DCT4/IDCT4.
* @param[in] *S points to an instance of the Q15 DCT4 structure.
* @param[in] *pState points to state buffer.
* @param[in,out] *pInlineBuffer points to the in-place input and output buffer.
* @return none.
*/
void arm_dct4_q15(
const arm_dct4_instance_q15 * S,
q15_t * pState,
q15_t * pInlineBuffer);
/**
* @brief Floating-point vector addition.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_add_f32(
float32_t * pSrcA,
float32_t * pSrcB,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Q7 vector addition.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_add_q7(
q7_t * pSrcA,
q7_t * pSrcB,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Q15 vector addition.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_add_q15(
q15_t * pSrcA,
q15_t * pSrcB,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Q31 vector addition.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_add_q31(
q31_t * pSrcA,
q31_t * pSrcB,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Floating-point vector subtraction.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_sub_f32(
float32_t * pSrcA,
float32_t * pSrcB,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Q7 vector subtraction.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_sub_q7(
q7_t * pSrcA,
q7_t * pSrcB,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Q15 vector subtraction.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_sub_q15(
q15_t * pSrcA,
q15_t * pSrcB,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Q31 vector subtraction.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_sub_q31(
q31_t * pSrcA,
q31_t * pSrcB,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Multiplies a floating-point vector by a scalar.
* @param[in] *pSrc points to the input vector
* @param[in] scale scale factor to be applied
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_scale_f32(
float32_t * pSrc,
float32_t scale,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Multiplies a Q7 vector by a scalar.
* @param[in] *pSrc points to the input vector
* @param[in] scaleFract fractional portion of the scale value
* @param[in] shift number of bits to shift the result by
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_scale_q7(
q7_t * pSrc,
q7_t scaleFract,
int8_t shift,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Multiplies a Q15 vector by a scalar.
* @param[in] *pSrc points to the input vector
* @param[in] scaleFract fractional portion of the scale value
* @param[in] shift number of bits to shift the result by
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_scale_q15(
q15_t * pSrc,
q15_t scaleFract,
int8_t shift,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Multiplies a Q31 vector by a scalar.
* @param[in] *pSrc points to the input vector
* @param[in] scaleFract fractional portion of the scale value
* @param[in] shift number of bits to shift the result by
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_scale_q31(
q31_t * pSrc,
q31_t scaleFract,
int8_t shift,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Q7 vector absolute value.
* @param[in] *pSrc points to the input buffer
* @param[out] *pDst points to the output buffer
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_abs_q7(
q7_t * pSrc,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Floating-point vector absolute value.
* @param[in] *pSrc points to the input buffer
* @param[out] *pDst points to the output buffer
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_abs_f32(
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Q15 vector absolute value.
* @param[in] *pSrc points to the input buffer
* @param[out] *pDst points to the output buffer
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_abs_q15(
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Q31 vector absolute value.
* @param[in] *pSrc points to the input buffer
* @param[out] *pDst points to the output buffer
* @param[in] blockSize number of samples in each vector
* @return none.
*/
void arm_abs_q31(
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Dot product of floating-point vectors.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[in] blockSize number of samples in each vector
* @param[out] *result output result returned here
* @return none.
*/
void arm_dot_prod_f32(
float32_t * pSrcA,
float32_t * pSrcB,
uint32_t blockSize,
float32_t * result);
/**
* @brief Dot product of Q7 vectors.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[in] blockSize number of samples in each vector
* @param[out] *result output result returned here
* @return none.
*/
void arm_dot_prod_q7(
q7_t * pSrcA,
q7_t * pSrcB,
uint32_t blockSize,
q31_t * result);
/**
* @brief Dot product of Q15 vectors.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[in] blockSize number of samples in each vector
* @param[out] *result output result returned here
* @return none.
*/
void arm_dot_prod_q15(
q15_t * pSrcA,
q15_t * pSrcB,
uint32_t blockSize,
q63_t * result);
/**
* @brief Dot product of Q31 vectors.
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[in] blockSize number of samples in each vector
* @param[out] *result output result returned here
* @return none.
*/
void arm_dot_prod_q31(
q31_t * pSrcA,
q31_t * pSrcB,
uint32_t blockSize,
q63_t * result);
/**
* @brief Shifts the elements of a Q7 vector a specified number of bits.
* @param[in] *pSrc points to the input vector
* @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right.
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_shift_q7(
q7_t * pSrc,
int8_t shiftBits,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Shifts the elements of a Q15 vector a specified number of bits.
* @param[in] *pSrc points to the input vector
* @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right.
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_shift_q15(
q15_t * pSrc,
int8_t shiftBits,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Shifts the elements of a Q31 vector a specified number of bits.
* @param[in] *pSrc points to the input vector
* @param[in] shiftBits number of bits to shift. A positive value shifts left; a negative value shifts right.
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_shift_q31(
q31_t * pSrc,
int8_t shiftBits,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Adds a constant offset to a floating-point vector.
* @param[in] *pSrc points to the input vector
* @param[in] offset is the offset to be added
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_offset_f32(
float32_t * pSrc,
float32_t offset,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Adds a constant offset to a Q7 vector.
* @param[in] *pSrc points to the input vector
* @param[in] offset is the offset to be added
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_offset_q7(
q7_t * pSrc,
q7_t offset,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Adds a constant offset to a Q15 vector.
* @param[in] *pSrc points to the input vector
* @param[in] offset is the offset to be added
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_offset_q15(
q15_t * pSrc,
q15_t offset,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Adds a constant offset to a Q31 vector.
* @param[in] *pSrc points to the input vector
* @param[in] offset is the offset to be added
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_offset_q31(
q31_t * pSrc,
q31_t offset,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Negates the elements of a floating-point vector.
* @param[in] *pSrc points to the input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_negate_f32(
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Negates the elements of a Q7 vector.
* @param[in] *pSrc points to the input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_negate_q7(
q7_t * pSrc,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Negates the elements of a Q15 vector.
* @param[in] *pSrc points to the input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_negate_q15(
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Negates the elements of a Q31 vector.
* @param[in] *pSrc points to the input vector
* @param[out] *pDst points to the output vector
* @param[in] blockSize number of samples in the vector
* @return none.
*/
void arm_negate_q31(
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Copies the elements of a floating-point vector.
* @param[in] *pSrc input pointer
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_copy_f32(
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Copies the elements of a Q7 vector.
* @param[in] *pSrc input pointer
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_copy_q7(
q7_t * pSrc,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Copies the elements of a Q15 vector.
* @param[in] *pSrc input pointer
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_copy_q15(
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Copies the elements of a Q31 vector.
* @param[in] *pSrc input pointer
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_copy_q31(
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Fills a constant value into a floating-point vector.
* @param[in] value input value to be filled
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_fill_f32(
float32_t value,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Fills a constant value into a Q7 vector.
* @param[in] value input value to be filled
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_fill_q7(
q7_t value,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Fills a constant value into a Q15 vector.
* @param[in] value input value to be filled
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_fill_q15(
q15_t value,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Fills a constant value into a Q31 vector.
* @param[in] value input value to be filled
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_fill_q31(
q31_t value,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Convolution of floating-point sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1.
* @return none.
*/
void arm_conv_f32(
float32_t * pSrcA,
uint32_t srcALen,
float32_t * pSrcB,
uint32_t srcBLen,
float32_t * pDst);
/**
* @brief Convolution of Q15 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length srcALen+srcBLen-1.
* @param[in] *pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.
* @param[in] *pScratch2 points to scratch buffer of size min(srcALen, srcBLen).
* @return none.
*/
void arm_conv_opt_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst,
q15_t * pScratch1,
q15_t * pScratch2);
/**
* @brief Convolution of Q15 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the location where the output result is written. Length srcALen+srcBLen-1.
* @return none.
*/
void arm_conv_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst);
/**
* @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length srcALen+srcBLen-1.
* @return none.
*/
void arm_conv_fast_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst);
/**
* @brief Convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length srcALen+srcBLen-1.
* @param[in] *pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.
* @param[in] *pScratch2 points to scratch buffer of size min(srcALen, srcBLen).
* @return none.
*/
void arm_conv_fast_opt_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst,
q15_t * pScratch1,
q15_t * pScratch2);
/**
* @brief Convolution of Q31 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length srcALen+srcBLen-1.
* @return none.
*/
void arm_conv_q31(
q31_t * pSrcA,
uint32_t srcALen,
q31_t * pSrcB,
uint32_t srcBLen,
q31_t * pDst);
/**
* @brief Convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length srcALen+srcBLen-1.
* @return none.
*/
void arm_conv_fast_q31(
q31_t * pSrcA,
uint32_t srcALen,
q31_t * pSrcB,
uint32_t srcBLen,
q31_t * pDst);
/**
* @brief Convolution of Q7 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length srcALen+srcBLen-1.
* @param[in] *pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.
* @param[in] *pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen).
* @return none.
*/
void arm_conv_opt_q7(
q7_t * pSrcA,
uint32_t srcALen,
q7_t * pSrcB,
uint32_t srcBLen,
q7_t * pDst,
q15_t * pScratch1,
q15_t * pScratch2);
/**
* @brief Convolution of Q7 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length srcALen+srcBLen-1.
* @return none.
*/
void arm_conv_q7(
q7_t * pSrcA,
uint32_t srcALen,
q7_t * pSrcB,
uint32_t srcBLen,
q7_t * pDst);
/**
* @brief Partial convolution of floating-point sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data
* @param[in] firstIndex is the first output sample to start with.
* @param[in] numPoints is the number of output points to be computed.
* @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
*/
arm_status arm_conv_partial_f32(
float32_t * pSrcA,
uint32_t srcALen,
float32_t * pSrcB,
uint32_t srcBLen,
float32_t * pDst,
uint32_t firstIndex,
uint32_t numPoints);
/**
* @brief Partial convolution of Q15 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data
* @param[in] firstIndex is the first output sample to start with.
* @param[in] numPoints is the number of output points to be computed.
* @param[in] * pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.
* @param[in] * pScratch2 points to scratch buffer of size min(srcALen, srcBLen).
* @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
*/
arm_status arm_conv_partial_opt_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst,
uint32_t firstIndex,
uint32_t numPoints,
q15_t * pScratch1,
q15_t * pScratch2);
/**
* @brief Partial convolution of Q15 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data
* @param[in] firstIndex is the first output sample to start with.
* @param[in] numPoints is the number of output points to be computed.
* @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
*/
arm_status arm_conv_partial_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst,
uint32_t firstIndex,
uint32_t numPoints);
/**
* @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data
* @param[in] firstIndex is the first output sample to start with.
* @param[in] numPoints is the number of output points to be computed.
* @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
*/
arm_status arm_conv_partial_fast_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst,
uint32_t firstIndex,
uint32_t numPoints);
/**
* @brief Partial convolution of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data
* @param[in] firstIndex is the first output sample to start with.
* @param[in] numPoints is the number of output points to be computed.
* @param[in] * pScratch1 points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.
* @param[in] * pScratch2 points to scratch buffer of size min(srcALen, srcBLen).
* @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
*/
arm_status arm_conv_partial_fast_opt_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst,
uint32_t firstIndex,
uint32_t numPoints,
q15_t * pScratch1,
q15_t * pScratch2);
/**
* @brief Partial convolution of Q31 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data
* @param[in] firstIndex is the first output sample to start with.
* @param[in] numPoints is the number of output points to be computed.
* @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
*/
arm_status arm_conv_partial_q31(
q31_t * pSrcA,
uint32_t srcALen,
q31_t * pSrcB,
uint32_t srcBLen,
q31_t * pDst,
uint32_t firstIndex,
uint32_t numPoints);
/**
* @brief Partial convolution of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data
* @param[in] firstIndex is the first output sample to start with.
* @param[in] numPoints is the number of output points to be computed.
* @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
*/
arm_status arm_conv_partial_fast_q31(
q31_t * pSrcA,
uint32_t srcALen,
q31_t * pSrcB,
uint32_t srcBLen,
q31_t * pDst,
uint32_t firstIndex,
uint32_t numPoints);
/**
* @brief Partial convolution of Q7 sequences
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data
* @param[in] firstIndex is the first output sample to start with.
* @param[in] numPoints is the number of output points to be computed.
* @param[in] *pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.
* @param[in] *pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen).
* @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
*/
arm_status arm_conv_partial_opt_q7(
q7_t * pSrcA,
uint32_t srcALen,
q7_t * pSrcB,
uint32_t srcBLen,
q7_t * pDst,
uint32_t firstIndex,
uint32_t numPoints,
q15_t * pScratch1,
q15_t * pScratch2);
/**
* @brief Partial convolution of Q7 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data
* @param[in] firstIndex is the first output sample to start with.
* @param[in] numPoints is the number of output points to be computed.
* @return Returns either ARM_MATH_SUCCESS if the function completed correctly or ARM_MATH_ARGUMENT_ERROR if the requested subset is not in the range [0 srcALen+srcBLen-2].
*/
arm_status arm_conv_partial_q7(
q7_t * pSrcA,
uint32_t srcALen,
q7_t * pSrcB,
uint32_t srcBLen,
q7_t * pDst,
uint32_t firstIndex,
uint32_t numPoints);
/**
* @brief Instance structure for the Q15 FIR decimator.
*/
typedef struct
{
uint8_t M; /**< decimation factor. */
uint16_t numTaps; /**< number of coefficients in the filter. */
q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/
q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
} arm_fir_decimate_instance_q15;
/**
* @brief Instance structure for the Q31 FIR decimator.
*/
typedef struct
{
uint8_t M; /**< decimation factor. */
uint16_t numTaps; /**< number of coefficients in the filter. */
q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/
q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
} arm_fir_decimate_instance_q31;
/**
* @brief Instance structure for the floating-point FIR decimator.
*/
typedef struct
{
uint8_t M; /**< decimation factor. */
uint16_t numTaps; /**< number of coefficients in the filter. */
float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/
float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
} arm_fir_decimate_instance_f32;
/**
* @brief Processing function for the floating-point FIR decimator.
* @param[in] *S points to an instance of the floating-point FIR decimator structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of input samples to process per call.
* @return none
*/
void arm_fir_decimate_f32(
const arm_fir_decimate_instance_f32 * S,
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the floating-point FIR decimator.
* @param[in,out] *S points to an instance of the floating-point FIR decimator structure.
* @param[in] numTaps number of coefficients in the filter.
* @param[in] M decimation factor.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of input samples to process per call.
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
* blockSize is not a multiple of M.
*/
arm_status arm_fir_decimate_init_f32(
arm_fir_decimate_instance_f32 * S,
uint16_t numTaps,
uint8_t M,
float32_t * pCoeffs,
float32_t * pState,
uint32_t blockSize);
/**
* @brief Processing function for the Q15 FIR decimator.
* @param[in] *S points to an instance of the Q15 FIR decimator structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of input samples to process per call.
* @return none
*/
void arm_fir_decimate_q15(
const arm_fir_decimate_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Processing function for the Q15 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4.
* @param[in] *S points to an instance of the Q15 FIR decimator structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of input samples to process per call.
* @return none
*/
void arm_fir_decimate_fast_q15(
const arm_fir_decimate_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q15 FIR decimator.
* @param[in,out] *S points to an instance of the Q15 FIR decimator structure.
* @param[in] numTaps number of coefficients in the filter.
* @param[in] M decimation factor.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of input samples to process per call.
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
* blockSize is not a multiple of M.
*/
arm_status arm_fir_decimate_init_q15(
arm_fir_decimate_instance_q15 * S,
uint16_t numTaps,
uint8_t M,
q15_t * pCoeffs,
q15_t * pState,
uint32_t blockSize);
/**
* @brief Processing function for the Q31 FIR decimator.
* @param[in] *S points to an instance of the Q31 FIR decimator structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of input samples to process per call.
* @return none
*/
void arm_fir_decimate_q31(
const arm_fir_decimate_instance_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Processing function for the Q31 FIR decimator (fast variant) for Cortex-M3 and Cortex-M4.
* @param[in] *S points to an instance of the Q31 FIR decimator structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of input samples to process per call.
* @return none
*/
void arm_fir_decimate_fast_q31(
arm_fir_decimate_instance_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q31 FIR decimator.
* @param[in,out] *S points to an instance of the Q31 FIR decimator structure.
* @param[in] numTaps number of coefficients in the filter.
* @param[in] M decimation factor.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of input samples to process per call.
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
* blockSize is not a multiple of M.
*/
arm_status arm_fir_decimate_init_q31(
arm_fir_decimate_instance_q31 * S,
uint16_t numTaps,
uint8_t M,
q31_t * pCoeffs,
q31_t * pState,
uint32_t blockSize);
/**
* @brief Instance structure for the Q15 FIR interpolator.
*/
typedef struct
{
uint8_t L; /**< upsample factor. */
uint16_t phaseLength; /**< length of each polyphase filter component. */
q15_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */
q15_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */
} arm_fir_interpolate_instance_q15;
/**
* @brief Instance structure for the Q31 FIR interpolator.
*/
typedef struct
{
uint8_t L; /**< upsample factor. */
uint16_t phaseLength; /**< length of each polyphase filter component. */
q31_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */
q31_t *pState; /**< points to the state variable array. The array is of length blockSize+phaseLength-1. */
} arm_fir_interpolate_instance_q31;
/**
* @brief Instance structure for the floating-point FIR interpolator.
*/
typedef struct
{
uint8_t L; /**< upsample factor. */
uint16_t phaseLength; /**< length of each polyphase filter component. */
float32_t *pCoeffs; /**< points to the coefficient array. The array is of length L*phaseLength. */
float32_t *pState; /**< points to the state variable array. The array is of length phaseLength+numTaps-1. */
} arm_fir_interpolate_instance_f32;
/**
* @brief Processing function for the Q15 FIR interpolator.
* @param[in] *S points to an instance of the Q15 FIR interpolator structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of input samples to process per call.
* @return none.
*/
void arm_fir_interpolate_q15(
const arm_fir_interpolate_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q15 FIR interpolator.
* @param[in,out] *S points to an instance of the Q15 FIR interpolator structure.
* @param[in] L upsample factor.
* @param[in] numTaps number of filter coefficients in the filter.
* @param[in] *pCoeffs points to the filter coefficient buffer.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of input samples to process per call.
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
* the filter length numTaps is not a multiple of the interpolation factor L.
*/
arm_status arm_fir_interpolate_init_q15(
arm_fir_interpolate_instance_q15 * S,
uint8_t L,
uint16_t numTaps,
q15_t * pCoeffs,
q15_t * pState,
uint32_t blockSize);
/**
* @brief Processing function for the Q31 FIR interpolator.
* @param[in] *S points to an instance of the Q15 FIR interpolator structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of input samples to process per call.
* @return none.
*/
void arm_fir_interpolate_q31(
const arm_fir_interpolate_instance_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q31 FIR interpolator.
* @param[in,out] *S points to an instance of the Q31 FIR interpolator structure.
* @param[in] L upsample factor.
* @param[in] numTaps number of filter coefficients in the filter.
* @param[in] *pCoeffs points to the filter coefficient buffer.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of input samples to process per call.
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
* the filter length numTaps is not a multiple of the interpolation factor L.
*/
arm_status arm_fir_interpolate_init_q31(
arm_fir_interpolate_instance_q31 * S,
uint8_t L,
uint16_t numTaps,
q31_t * pCoeffs,
q31_t * pState,
uint32_t blockSize);
/**
* @brief Processing function for the floating-point FIR interpolator.
* @param[in] *S points to an instance of the floating-point FIR interpolator structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of input samples to process per call.
* @return none.
*/
void arm_fir_interpolate_f32(
const arm_fir_interpolate_instance_f32 * S,
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the floating-point FIR interpolator.
* @param[in,out] *S points to an instance of the floating-point FIR interpolator structure.
* @param[in] L upsample factor.
* @param[in] numTaps number of filter coefficients in the filter.
* @param[in] *pCoeffs points to the filter coefficient buffer.
* @param[in] *pState points to the state buffer.
* @param[in] blockSize number of input samples to process per call.
* @return The function returns ARM_MATH_SUCCESS if initialization is successful or ARM_MATH_LENGTH_ERROR if
* the filter length numTaps is not a multiple of the interpolation factor L.
*/
arm_status arm_fir_interpolate_init_f32(
arm_fir_interpolate_instance_f32 * S,
uint8_t L,
uint16_t numTaps,
float32_t * pCoeffs,
float32_t * pState,
uint32_t blockSize);
/**
* @brief Instance structure for the high precision Q31 Biquad cascade filter.
*/
typedef struct
{
uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */
q63_t *pState; /**< points to the array of state coefficients. The array is of length 4*numStages. */
q31_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */
uint8_t postShift; /**< additional shift, in bits, applied to each output sample. */
} arm_biquad_cas_df1_32x64_ins_q31;
/**
* @param[in] *S points to an instance of the high precision Q31 Biquad cascade filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_biquad_cas_df1_32x64_q31(
const arm_biquad_cas_df1_32x64_ins_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @param[in,out] *S points to an instance of the high precision Q31 Biquad cascade filter structure.
* @param[in] numStages number of 2nd order stages in the filter.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] postShift shift to be applied to the output. Varies according to the coefficients format
* @return none
*/
void arm_biquad_cas_df1_32x64_init_q31(
arm_biquad_cas_df1_32x64_ins_q31 * S,
uint8_t numStages,
q31_t * pCoeffs,
q63_t * pState,
uint8_t postShift);
/**
* @brief Instance structure for the floating-point transposed direct form II Biquad cascade filter.
*/
typedef struct
{
uint8_t numStages; /**< number of 2nd order stages in the filter. Overall order is 2*numStages. */
float32_t *pState; /**< points to the array of state coefficients. The array is of length 2*numStages. */
float32_t *pCoeffs; /**< points to the array of coefficients. The array is of length 5*numStages. */
} arm_biquad_cascade_df2T_instance_f32;
/**
* @brief Processing function for the floating-point transposed direct form II Biquad cascade filter.
* @param[in] *S points to an instance of the filter data structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_biquad_cascade_df2T_f32(
const arm_biquad_cascade_df2T_instance_f32 * S,
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the floating-point transposed direct form II Biquad cascade filter.
* @param[in,out] *S points to an instance of the filter data structure.
* @param[in] numStages number of 2nd order stages in the filter.
* @param[in] *pCoeffs points to the filter coefficients.
* @param[in] *pState points to the state buffer.
* @return none
*/
void arm_biquad_cascade_df2T_init_f32(
arm_biquad_cascade_df2T_instance_f32 * S,
uint8_t numStages,
float32_t * pCoeffs,
float32_t * pState);
/**
* @brief Instance structure for the Q15 FIR lattice filter.
*/
typedef struct
{
uint16_t numStages; /**< number of filter stages. */
q15_t *pState; /**< points to the state variable array. The array is of length numStages. */
q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */
} arm_fir_lattice_instance_q15;
/**
* @brief Instance structure for the Q31 FIR lattice filter.
*/
typedef struct
{
uint16_t numStages; /**< number of filter stages. */
q31_t *pState; /**< points to the state variable array. The array is of length numStages. */
q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */
} arm_fir_lattice_instance_q31;
/**
* @brief Instance structure for the floating-point FIR lattice filter.
*/
typedef struct
{
uint16_t numStages; /**< number of filter stages. */
float32_t *pState; /**< points to the state variable array. The array is of length numStages. */
float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numStages. */
} arm_fir_lattice_instance_f32;
/**
* @brief Initialization function for the Q15 FIR lattice filter.
* @param[in] *S points to an instance of the Q15 FIR lattice structure.
* @param[in] numStages number of filter stages.
* @param[in] *pCoeffs points to the coefficient buffer. The array is of length numStages.
* @param[in] *pState points to the state buffer. The array is of length numStages.
* @return none.
*/
void arm_fir_lattice_init_q15(
arm_fir_lattice_instance_q15 * S,
uint16_t numStages,
q15_t * pCoeffs,
q15_t * pState);
/**
* @brief Processing function for the Q15 FIR lattice filter.
* @param[in] *S points to an instance of the Q15 FIR lattice structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_fir_lattice_q15(
const arm_fir_lattice_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q31 FIR lattice filter.
* @param[in] *S points to an instance of the Q31 FIR lattice structure.
* @param[in] numStages number of filter stages.
* @param[in] *pCoeffs points to the coefficient buffer. The array is of length numStages.
* @param[in] *pState points to the state buffer. The array is of length numStages.
* @return none.
*/
void arm_fir_lattice_init_q31(
arm_fir_lattice_instance_q31 * S,
uint16_t numStages,
q31_t * pCoeffs,
q31_t * pState);
/**
* @brief Processing function for the Q31 FIR lattice filter.
* @param[in] *S points to an instance of the Q31 FIR lattice structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_fir_lattice_q31(
const arm_fir_lattice_instance_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the floating-point FIR lattice filter.
* @param[in] *S points to an instance of the floating-point FIR lattice structure.
* @param[in] numStages number of filter stages.
* @param[in] *pCoeffs points to the coefficient buffer. The array is of length numStages.
* @param[in] *pState points to the state buffer. The array is of length numStages.
* @return none.
*/
void arm_fir_lattice_init_f32(
arm_fir_lattice_instance_f32 * S,
uint16_t numStages,
float32_t * pCoeffs,
float32_t * pState);
/**
* @brief Processing function for the floating-point FIR lattice filter.
* @param[in] *S points to an instance of the floating-point FIR lattice structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_fir_lattice_f32(
const arm_fir_lattice_instance_f32 * S,
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Instance structure for the Q15 IIR lattice filter.
*/
typedef struct
{
uint16_t numStages; /**< number of stages in the filter. */
q15_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */
q15_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */
q15_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */
} arm_iir_lattice_instance_q15;
/**
* @brief Instance structure for the Q31 IIR lattice filter.
*/
typedef struct
{
uint16_t numStages; /**< number of stages in the filter. */
q31_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */
q31_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */
q31_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */
} arm_iir_lattice_instance_q31;
/**
* @brief Instance structure for the floating-point IIR lattice filter.
*/
typedef struct
{
uint16_t numStages; /**< number of stages in the filter. */
float32_t *pState; /**< points to the state variable array. The array is of length numStages+blockSize. */
float32_t *pkCoeffs; /**< points to the reflection coefficient array. The array is of length numStages. */
float32_t *pvCoeffs; /**< points to the ladder coefficient array. The array is of length numStages+1. */
} arm_iir_lattice_instance_f32;
/**
* @brief Processing function for the floating-point IIR lattice filter.
* @param[in] *S points to an instance of the floating-point IIR lattice structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_iir_lattice_f32(
const arm_iir_lattice_instance_f32 * S,
float32_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the floating-point IIR lattice filter.
* @param[in] *S points to an instance of the floating-point IIR lattice structure.
* @param[in] numStages number of stages in the filter.
* @param[in] *pkCoeffs points to the reflection coefficient buffer. The array is of length numStages.
* @param[in] *pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1.
* @param[in] *pState points to the state buffer. The array is of length numStages+blockSize-1.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_iir_lattice_init_f32(
arm_iir_lattice_instance_f32 * S,
uint16_t numStages,
float32_t * pkCoeffs,
float32_t * pvCoeffs,
float32_t * pState,
uint32_t blockSize);
/**
* @brief Processing function for the Q31 IIR lattice filter.
* @param[in] *S points to an instance of the Q31 IIR lattice structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_iir_lattice_q31(
const arm_iir_lattice_instance_q31 * S,
q31_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q31 IIR lattice filter.
* @param[in] *S points to an instance of the Q31 IIR lattice structure.
* @param[in] numStages number of stages in the filter.
* @param[in] *pkCoeffs points to the reflection coefficient buffer. The array is of length numStages.
* @param[in] *pvCoeffs points to the ladder coefficient buffer. The array is of length numStages+1.
* @param[in] *pState points to the state buffer. The array is of length numStages+blockSize.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_iir_lattice_init_q31(
arm_iir_lattice_instance_q31 * S,
uint16_t numStages,
q31_t * pkCoeffs,
q31_t * pvCoeffs,
q31_t * pState,
uint32_t blockSize);
/**
* @brief Processing function for the Q15 IIR lattice filter.
* @param[in] *S points to an instance of the Q15 IIR lattice structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_iir_lattice_q15(
const arm_iir_lattice_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Initialization function for the Q15 IIR lattice filter.
* @param[in] *S points to an instance of the fixed-point Q15 IIR lattice structure.
* @param[in] numStages number of stages in the filter.
* @param[in] *pkCoeffs points to reflection coefficient buffer. The array is of length numStages.
* @param[in] *pvCoeffs points to ladder coefficient buffer. The array is of length numStages+1.
* @param[in] *pState points to state buffer. The array is of length numStages+blockSize.
* @param[in] blockSize number of samples to process per call.
* @return none.
*/
void arm_iir_lattice_init_q15(
arm_iir_lattice_instance_q15 * S,
uint16_t numStages,
q15_t * pkCoeffs,
q15_t * pvCoeffs,
q15_t * pState,
uint32_t blockSize);
/**
* @brief Instance structure for the floating-point LMS filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of coefficients in the filter. */
float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */
float32_t mu; /**< step size that controls filter coefficient updates. */
} arm_lms_instance_f32;
/**
* @brief Processing function for floating-point LMS filter.
* @param[in] *S points to an instance of the floating-point LMS filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[in] *pRef points to the block of reference data.
* @param[out] *pOut points to the block of output data.
* @param[out] *pErr points to the block of error data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_lms_f32(
const arm_lms_instance_f32 * S,
float32_t * pSrc,
float32_t * pRef,
float32_t * pOut,
float32_t * pErr,
uint32_t blockSize);
/**
* @brief Initialization function for floating-point LMS filter.
* @param[in] *S points to an instance of the floating-point LMS filter structure.
* @param[in] numTaps number of filter coefficients.
* @param[in] *pCoeffs points to the coefficient buffer.
* @param[in] *pState points to state buffer.
* @param[in] mu step size that controls filter coefficient updates.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_lms_init_f32(
arm_lms_instance_f32 * S,
uint16_t numTaps,
float32_t * pCoeffs,
float32_t * pState,
float32_t mu,
uint32_t blockSize);
/**
* @brief Instance structure for the Q15 LMS filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of coefficients in the filter. */
q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */
q15_t mu; /**< step size that controls filter coefficient updates. */
uint32_t postShift; /**< bit shift applied to coefficients. */
} arm_lms_instance_q15;
/**
* @brief Initialization function for the Q15 LMS filter.
* @param[in] *S points to an instance of the Q15 LMS filter structure.
* @param[in] numTaps number of filter coefficients.
* @param[in] *pCoeffs points to the coefficient buffer.
* @param[in] *pState points to the state buffer.
* @param[in] mu step size that controls filter coefficient updates.
* @param[in] blockSize number of samples to process.
* @param[in] postShift bit shift applied to coefficients.
* @return none.
*/
void arm_lms_init_q15(
arm_lms_instance_q15 * S,
uint16_t numTaps,
q15_t * pCoeffs,
q15_t * pState,
q15_t mu,
uint32_t blockSize,
uint32_t postShift);
/**
* @brief Processing function for Q15 LMS filter.
* @param[in] *S points to an instance of the Q15 LMS filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[in] *pRef points to the block of reference data.
* @param[out] *pOut points to the block of output data.
* @param[out] *pErr points to the block of error data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_lms_q15(
const arm_lms_instance_q15 * S,
q15_t * pSrc,
q15_t * pRef,
q15_t * pOut,
q15_t * pErr,
uint32_t blockSize);
/**
* @brief Instance structure for the Q31 LMS filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of coefficients in the filter. */
q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */
q31_t mu; /**< step size that controls filter coefficient updates. */
uint32_t postShift; /**< bit shift applied to coefficients. */
} arm_lms_instance_q31;
/**
* @brief Processing function for Q31 LMS filter.
* @param[in] *S points to an instance of the Q15 LMS filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[in] *pRef points to the block of reference data.
* @param[out] *pOut points to the block of output data.
* @param[out] *pErr points to the block of error data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_lms_q31(
const arm_lms_instance_q31 * S,
q31_t * pSrc,
q31_t * pRef,
q31_t * pOut,
q31_t * pErr,
uint32_t blockSize);
/**
* @brief Initialization function for Q31 LMS filter.
* @param[in] *S points to an instance of the Q31 LMS filter structure.
* @param[in] numTaps number of filter coefficients.
* @param[in] *pCoeffs points to coefficient buffer.
* @param[in] *pState points to state buffer.
* @param[in] mu step size that controls filter coefficient updates.
* @param[in] blockSize number of samples to process.
* @param[in] postShift bit shift applied to coefficients.
* @return none.
*/
void arm_lms_init_q31(
arm_lms_instance_q31 * S,
uint16_t numTaps,
q31_t * pCoeffs,
q31_t * pState,
q31_t mu,
uint32_t blockSize,
uint32_t postShift);
/**
* @brief Instance structure for the floating-point normalized LMS filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of coefficients in the filter. */
float32_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */
float32_t mu; /**< step size that control filter coefficient updates. */
float32_t energy; /**< saves previous frame energy. */
float32_t x0; /**< saves previous input sample. */
} arm_lms_norm_instance_f32;
/**
* @brief Processing function for floating-point normalized LMS filter.
* @param[in] *S points to an instance of the floating-point normalized LMS filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[in] *pRef points to the block of reference data.
* @param[out] *pOut points to the block of output data.
* @param[out] *pErr points to the block of error data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_lms_norm_f32(
arm_lms_norm_instance_f32 * S,
float32_t * pSrc,
float32_t * pRef,
float32_t * pOut,
float32_t * pErr,
uint32_t blockSize);
/**
* @brief Initialization function for floating-point normalized LMS filter.
* @param[in] *S points to an instance of the floating-point LMS filter structure.
* @param[in] numTaps number of filter coefficients.
* @param[in] *pCoeffs points to coefficient buffer.
* @param[in] *pState points to state buffer.
* @param[in] mu step size that controls filter coefficient updates.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_lms_norm_init_f32(
arm_lms_norm_instance_f32 * S,
uint16_t numTaps,
float32_t * pCoeffs,
float32_t * pState,
float32_t mu,
uint32_t blockSize);
/**
* @brief Instance structure for the Q31 normalized LMS filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of coefficients in the filter. */
q31_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */
q31_t mu; /**< step size that controls filter coefficient updates. */
uint8_t postShift; /**< bit shift applied to coefficients. */
q31_t *recipTable; /**< points to the reciprocal initial value table. */
q31_t energy; /**< saves previous frame energy. */
q31_t x0; /**< saves previous input sample. */
} arm_lms_norm_instance_q31;
/**
* @brief Processing function for Q31 normalized LMS filter.
* @param[in] *S points to an instance of the Q31 normalized LMS filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[in] *pRef points to the block of reference data.
* @param[out] *pOut points to the block of output data.
* @param[out] *pErr points to the block of error data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_lms_norm_q31(
arm_lms_norm_instance_q31 * S,
q31_t * pSrc,
q31_t * pRef,
q31_t * pOut,
q31_t * pErr,
uint32_t blockSize);
/**
* @brief Initialization function for Q31 normalized LMS filter.
* @param[in] *S points to an instance of the Q31 normalized LMS filter structure.
* @param[in] numTaps number of filter coefficients.
* @param[in] *pCoeffs points to coefficient buffer.
* @param[in] *pState points to state buffer.
* @param[in] mu step size that controls filter coefficient updates.
* @param[in] blockSize number of samples to process.
* @param[in] postShift bit shift applied to coefficients.
* @return none.
*/
void arm_lms_norm_init_q31(
arm_lms_norm_instance_q31 * S,
uint16_t numTaps,
q31_t * pCoeffs,
q31_t * pState,
q31_t mu,
uint32_t blockSize,
uint8_t postShift);
/**
* @brief Instance structure for the Q15 normalized LMS filter.
*/
typedef struct
{
uint16_t numTaps; /**< Number of coefficients in the filter. */
q15_t *pState; /**< points to the state variable array. The array is of length numTaps+blockSize-1. */
q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps. */
q15_t mu; /**< step size that controls filter coefficient updates. */
uint8_t postShift; /**< bit shift applied to coefficients. */
q15_t *recipTable; /**< Points to the reciprocal initial value table. */
q15_t energy; /**< saves previous frame energy. */
q15_t x0; /**< saves previous input sample. */
} arm_lms_norm_instance_q15;
/**
* @brief Processing function for Q15 normalized LMS filter.
* @param[in] *S points to an instance of the Q15 normalized LMS filter structure.
* @param[in] *pSrc points to the block of input data.
* @param[in] *pRef points to the block of reference data.
* @param[out] *pOut points to the block of output data.
* @param[out] *pErr points to the block of error data.
* @param[in] blockSize number of samples to process.
* @return none.
*/
void arm_lms_norm_q15(
arm_lms_norm_instance_q15 * S,
q15_t * pSrc,
q15_t * pRef,
q15_t * pOut,
q15_t * pErr,
uint32_t blockSize);
/**
* @brief Initialization function for Q15 normalized LMS filter.
* @param[in] *S points to an instance of the Q15 normalized LMS filter structure.
* @param[in] numTaps number of filter coefficients.
* @param[in] *pCoeffs points to coefficient buffer.
* @param[in] *pState points to state buffer.
* @param[in] mu step size that controls filter coefficient updates.
* @param[in] blockSize number of samples to process.
* @param[in] postShift bit shift applied to coefficients.
* @return none.
*/
void arm_lms_norm_init_q15(
arm_lms_norm_instance_q15 * S,
uint16_t numTaps,
q15_t * pCoeffs,
q15_t * pState,
q15_t mu,
uint32_t blockSize,
uint8_t postShift);
/**
* @brief Correlation of floating-point sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1.
* @return none.
*/
void arm_correlate_f32(
float32_t * pSrcA,
uint32_t srcALen,
float32_t * pSrcB,
uint32_t srcBLen,
float32_t * pDst);
/**
* @brief Correlation of Q15 sequences
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1.
* @param[in] *pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.
* @return none.
*/
void arm_correlate_opt_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst,
q15_t * pScratch);
/**
* @brief Correlation of Q15 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1.
* @return none.
*/
void arm_correlate_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst);
/**
* @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1.
* @return none.
*/
void arm_correlate_fast_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst);
/**
* @brief Correlation of Q15 sequences (fast version) for Cortex-M3 and Cortex-M4.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1.
* @param[in] *pScratch points to scratch buffer of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.
* @return none.
*/
void arm_correlate_fast_opt_q15(
q15_t * pSrcA,
uint32_t srcALen,
q15_t * pSrcB,
uint32_t srcBLen,
q15_t * pDst,
q15_t * pScratch);
/**
* @brief Correlation of Q31 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1.
* @return none.
*/
void arm_correlate_q31(
q31_t * pSrcA,
uint32_t srcALen,
q31_t * pSrcB,
uint32_t srcBLen,
q31_t * pDst);
/**
* @brief Correlation of Q31 sequences (fast version) for Cortex-M3 and Cortex-M4
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1.
* @return none.
*/
void arm_correlate_fast_q31(
q31_t * pSrcA,
uint32_t srcALen,
q31_t * pSrcB,
uint32_t srcBLen,
q31_t * pDst);
/**
* @brief Correlation of Q7 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1.
* @param[in] *pScratch1 points to scratch buffer(of type q15_t) of size max(srcALen, srcBLen) + 2*min(srcALen, srcBLen) - 2.
* @param[in] *pScratch2 points to scratch buffer (of type q15_t) of size min(srcALen, srcBLen).
* @return none.
*/
void arm_correlate_opt_q7(
q7_t * pSrcA,
uint32_t srcALen,
q7_t * pSrcB,
uint32_t srcBLen,
q7_t * pDst,
q15_t * pScratch1,
q15_t * pScratch2);
/**
* @brief Correlation of Q7 sequences.
* @param[in] *pSrcA points to the first input sequence.
* @param[in] srcALen length of the first input sequence.
* @param[in] *pSrcB points to the second input sequence.
* @param[in] srcBLen length of the second input sequence.
* @param[out] *pDst points to the block of output data Length 2 * max(srcALen, srcBLen) - 1.
* @return none.
*/
void arm_correlate_q7(
q7_t * pSrcA,
uint32_t srcALen,
q7_t * pSrcB,
uint32_t srcBLen,
q7_t * pDst);
/**
* @brief Instance structure for the floating-point sparse FIR filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of coefficients in the filter. */
uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */
float32_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */
float32_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/
uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */
int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */
} arm_fir_sparse_instance_f32;
/**
* @brief Instance structure for the Q31 sparse FIR filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of coefficients in the filter. */
uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */
q31_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */
q31_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/
uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */
int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */
} arm_fir_sparse_instance_q31;
/**
* @brief Instance structure for the Q15 sparse FIR filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of coefficients in the filter. */
uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */
q15_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */
q15_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/
uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */
int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */
} arm_fir_sparse_instance_q15;
/**
* @brief Instance structure for the Q7 sparse FIR filter.
*/
typedef struct
{
uint16_t numTaps; /**< number of coefficients in the filter. */
uint16_t stateIndex; /**< state buffer index. Points to the oldest sample in the state buffer. */
q7_t *pState; /**< points to the state buffer array. The array is of length maxDelay+blockSize-1. */
q7_t *pCoeffs; /**< points to the coefficient array. The array is of length numTaps.*/
uint16_t maxDelay; /**< maximum offset specified by the pTapDelay array. */
int32_t *pTapDelay; /**< points to the array of delay values. The array is of length numTaps. */
} arm_fir_sparse_instance_q7;
/**
* @brief Processing function for the floating-point sparse FIR filter.
* @param[in] *S points to an instance of the floating-point sparse FIR structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] *pScratchIn points to a temporary buffer of size blockSize.
* @param[in] blockSize number of input samples to process per call.
* @return none.
*/
void arm_fir_sparse_f32(
arm_fir_sparse_instance_f32 * S,
float32_t * pSrc,
float32_t * pDst,
float32_t * pScratchIn,
uint32_t blockSize);
/**
* @brief Initialization function for the floating-point sparse FIR filter.
* @param[in,out] *S points to an instance of the floating-point sparse FIR structure.
* @param[in] numTaps number of nonzero coefficients in the filter.
* @param[in] *pCoeffs points to the array of filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] *pTapDelay points to the array of offset times.
* @param[in] maxDelay maximum offset time supported.
* @param[in] blockSize number of samples that will be processed per block.
* @return none
*/
void arm_fir_sparse_init_f32(
arm_fir_sparse_instance_f32 * S,
uint16_t numTaps,
float32_t * pCoeffs,
float32_t * pState,
int32_t * pTapDelay,
uint16_t maxDelay,
uint32_t blockSize);
/**
* @brief Processing function for the Q31 sparse FIR filter.
* @param[in] *S points to an instance of the Q31 sparse FIR structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] *pScratchIn points to a temporary buffer of size blockSize.
* @param[in] blockSize number of input samples to process per call.
* @return none.
*/
void arm_fir_sparse_q31(
arm_fir_sparse_instance_q31 * S,
q31_t * pSrc,
q31_t * pDst,
q31_t * pScratchIn,
uint32_t blockSize);
/**
* @brief Initialization function for the Q31 sparse FIR filter.
* @param[in,out] *S points to an instance of the Q31 sparse FIR structure.
* @param[in] numTaps number of nonzero coefficients in the filter.
* @param[in] *pCoeffs points to the array of filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] *pTapDelay points to the array of offset times.
* @param[in] maxDelay maximum offset time supported.
* @param[in] blockSize number of samples that will be processed per block.
* @return none
*/
void arm_fir_sparse_init_q31(
arm_fir_sparse_instance_q31 * S,
uint16_t numTaps,
q31_t * pCoeffs,
q31_t * pState,
int32_t * pTapDelay,
uint16_t maxDelay,
uint32_t blockSize);
/**
* @brief Processing function for the Q15 sparse FIR filter.
* @param[in] *S points to an instance of the Q15 sparse FIR structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] *pScratchIn points to a temporary buffer of size blockSize.
* @param[in] *pScratchOut points to a temporary buffer of size blockSize.
* @param[in] blockSize number of input samples to process per call.
* @return none.
*/
void arm_fir_sparse_q15(
arm_fir_sparse_instance_q15 * S,
q15_t * pSrc,
q15_t * pDst,
q15_t * pScratchIn,
q31_t * pScratchOut,
uint32_t blockSize);
/**
* @brief Initialization function for the Q15 sparse FIR filter.
* @param[in,out] *S points to an instance of the Q15 sparse FIR structure.
* @param[in] numTaps number of nonzero coefficients in the filter.
* @param[in] *pCoeffs points to the array of filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] *pTapDelay points to the array of offset times.
* @param[in] maxDelay maximum offset time supported.
* @param[in] blockSize number of samples that will be processed per block.
* @return none
*/
void arm_fir_sparse_init_q15(
arm_fir_sparse_instance_q15 * S,
uint16_t numTaps,
q15_t * pCoeffs,
q15_t * pState,
int32_t * pTapDelay,
uint16_t maxDelay,
uint32_t blockSize);
/**
* @brief Processing function for the Q7 sparse FIR filter.
* @param[in] *S points to an instance of the Q7 sparse FIR structure.
* @param[in] *pSrc points to the block of input data.
* @param[out] *pDst points to the block of output data
* @param[in] *pScratchIn points to a temporary buffer of size blockSize.
* @param[in] *pScratchOut points to a temporary buffer of size blockSize.
* @param[in] blockSize number of input samples to process per call.
* @return none.
*/
void arm_fir_sparse_q7(
arm_fir_sparse_instance_q7 * S,
q7_t * pSrc,
q7_t * pDst,
q7_t * pScratchIn,
q31_t * pScratchOut,
uint32_t blockSize);
/**
* @brief Initialization function for the Q7 sparse FIR filter.
* @param[in,out] *S points to an instance of the Q7 sparse FIR structure.
* @param[in] numTaps number of nonzero coefficients in the filter.
* @param[in] *pCoeffs points to the array of filter coefficients.
* @param[in] *pState points to the state buffer.
* @param[in] *pTapDelay points to the array of offset times.
* @param[in] maxDelay maximum offset time supported.
* @param[in] blockSize number of samples that will be processed per block.
* @return none
*/
void arm_fir_sparse_init_q7(
arm_fir_sparse_instance_q7 * S,
uint16_t numTaps,
q7_t * pCoeffs,
q7_t * pState,
int32_t * pTapDelay,
uint16_t maxDelay,
uint32_t blockSize);
/*
* @brief Floating-point sin_cos function.
* @param[in] theta input value in degrees
* @param[out] *pSinVal points to the processed sine output.
* @param[out] *pCosVal points to the processed cos output.
* @return none.
*/
void arm_sin_cos_f32(
float32_t theta,
float32_t * pSinVal,
float32_t * pCcosVal);
/*
* @brief Q31 sin_cos function.
* @param[in] theta scaled input value in degrees
* @param[out] *pSinVal points to the processed sine output.
* @param[out] *pCosVal points to the processed cosine output.
* @return none.
*/
void arm_sin_cos_q31(
q31_t theta,
q31_t * pSinVal,
q31_t * pCosVal);
/**
* @brief Floating-point complex conjugate.
* @param[in] *pSrc points to the input vector
* @param[out] *pDst points to the output vector
* @param[in] numSamples number of complex samples in each vector
* @return none.
*/
void arm_cmplx_conj_f32(
float32_t * pSrc,
float32_t * pDst,
uint32_t numSamples);
/**
* @brief Q31 complex conjugate.
* @param[in] *pSrc points to the input vector
* @param[out] *pDst points to the output vector
* @param[in] numSamples number of complex samples in each vector
* @return none.
*/
void arm_cmplx_conj_q31(
q31_t * pSrc,
q31_t * pDst,
uint32_t numSamples);
/**
* @brief Q15 complex conjugate.
* @param[in] *pSrc points to the input vector
* @param[out] *pDst points to the output vector
* @param[in] numSamples number of complex samples in each vector
* @return none.
*/
void arm_cmplx_conj_q15(
q15_t * pSrc,
q15_t * pDst,
uint32_t numSamples);
/**
* @brief Floating-point complex magnitude squared
* @param[in] *pSrc points to the complex input vector
* @param[out] *pDst points to the real output vector
* @param[in] numSamples number of complex samples in the input vector
* @return none.
*/
void arm_cmplx_mag_squared_f32(
float32_t * pSrc,
float32_t * pDst,
uint32_t numSamples);
/**
* @brief Q31 complex magnitude squared
* @param[in] *pSrc points to the complex input vector
* @param[out] *pDst points to the real output vector
* @param[in] numSamples number of complex samples in the input vector
* @return none.
*/
void arm_cmplx_mag_squared_q31(
q31_t * pSrc,
q31_t * pDst,
uint32_t numSamples);
/**
* @brief Q15 complex magnitude squared
* @param[in] *pSrc points to the complex input vector
* @param[out] *pDst points to the real output vector
* @param[in] numSamples number of complex samples in the input vector
* @return none.
*/
void arm_cmplx_mag_squared_q15(
q15_t * pSrc,
q15_t * pDst,
uint32_t numSamples);
/**
* @ingroup groupController
*/
/**
* @defgroup PID PID Motor Control
*
* A Proportional Integral Derivative (PID) controller is a generic feedback control
* loop mechanism widely used in industrial control systems.
* A PID controller is the most commonly used type of feedback controller.
*
* This set of functions implements (PID) controllers
* for Q15, Q31, and floating-point data types. The functions operate on a single sample
* of data and each call to the function returns a single processed value.
* S points to an instance of the PID control data structure. in
* is the input sample value. The functions return the output value.
*
* \par Algorithm:
*
*
* \par
* where \c Kp is proportional constant, \c Ki is Integral constant and \c Kd is Derivative constant
*
* \par
* \image html PID.gif "Proportional Integral Derivative Controller"
*
* \par
* The PID controller calculates an "error" value as the difference between
* the measured output and the reference input.
* The controller attempts to minimize the error by adjusting the process control inputs.
* The proportional value determines the reaction to the current error,
* the integral value determines the reaction based on the sum of recent errors,
* and the derivative value determines the reaction based on the rate at which the error has been changing.
*
* \par Instance Structure
* The Gains A0, A1, A2 and state variables for a PID controller are stored together in an instance data structure.
* A separate instance structure must be defined for each PID Controller.
* There are separate instance structure declarations for each of the 3 supported data types.
*
* \par Reset Functions
* There is also an associated reset function for each data type which clears the state array.
*
* \par Initialization Functions
* There is also an associated initialization function for each data type.
* The initialization function performs the following operations:
* - Initializes the Gains A0, A1, A2 from Kp,Ki, Kd gains.
* - Zeros out the values in the state buffer.
*
* \par
* Instance structure cannot be placed into a const data section and it is recommended to use the initialization function.
*
* \par Fixed-Point Behavior
* Care must be taken when using the fixed-point versions of the PID Controller functions.
* In particular, the overflow and saturation behavior of the accumulator used in each function must be considered.
* Refer to the function specific documentation below for usage guidelines.
*/
/**
* @addtogroup PID
* @{
*/
/**
* @brief Process function for the floating-point PID Control.
* @param[in,out] *S is an instance of the floating-point PID Control structure
* @param[in] in input sample to process
* @return out processed output sample.
*/
static __INLINE float32_t arm_pid_f32(
arm_pid_instance_f32 * S,
float32_t in)
{
float32_t out;
/* y[n] = y[n-1] + A0 * x[n] + A1 * x[n-1] + A2 * x[n-2] */
out = (S->A0 * in) +
(S->A1 * S->state[0]) + (S->A2 * S->state[1]) + (S->state[2]);
/* Update state */
S->state[1] = S->state[0];
S->state[0] = in;
S->state[2] = out;
/* return to application */
return (out);
}
/**
* @brief Process function for the Q31 PID Control.
* @param[in,out] *S points to an instance of the Q31 PID Control structure
* @param[in] in input sample to process
* @return out processed output sample.
*
* Scaling and Overflow Behavior:
* \par
* The function is implemented using an internal 64-bit accumulator.
* The accumulator has a 2.62 format and maintains full precision of the intermediate multiplication results but provides only a single guard bit.
* Thus, if the accumulator result overflows it wraps around rather than clip.
* In order to avoid overflows completely the input signal must be scaled down by 2 bits as there are four additions.
* After all multiply-accumulates are performed, the 2.62 accumulator is truncated to 1.32 format and then saturated to 1.31 format.
*/
static __INLINE q31_t arm_pid_q31(
arm_pid_instance_q31 * S,
q31_t in)
{
q63_t acc;
q31_t out;
/* acc = A0 * x[n] */
acc = (q63_t) S->A0 * in;
/* acc += A1 * x[n-1] */
acc += (q63_t) S->A1 * S->state[0];
/* acc += A2 * x[n-2] */
acc += (q63_t) S->A2 * S->state[1];
/* convert output to 1.31 format to add y[n-1] */
out = (q31_t) (acc >> 31u);
/* out += y[n-1] */
out += S->state[2];
/* Update state */
S->state[1] = S->state[0];
S->state[0] = in;
S->state[2] = out;
/* return to application */
return (out);
}
/**
* @brief Process function for the Q15 PID Control.
* @param[in,out] *S points to an instance of the Q15 PID Control structure
* @param[in] in input sample to process
* @return out processed output sample.
*
* Scaling and Overflow Behavior:
* \par
* The function is implemented using a 64-bit internal accumulator.
* Both Gains and state variables are represented in 1.15 format and multiplications yield a 2.30 result.
* The 2.30 intermediate results are accumulated in a 64-bit accumulator in 34.30 format.
* There is no risk of internal overflow with this approach and the full precision of intermediate multiplications is preserved.
* After all additions have been performed, the accumulator is truncated to 34.15 format by discarding low 15 bits.
* Lastly, the accumulator is saturated to yield a result in 1.15 format.
*/
static __INLINE q15_t arm_pid_q15(
arm_pid_instance_q15 * S,
q15_t in)
{
q63_t acc;
q15_t out;
#ifndef ARM_MATH_CM0_FAMILY
__SIMD32_TYPE *vstate;
/* Implementation of PID controller */
/* acc = A0 * x[n] */
acc = (q31_t) __SMUAD(S->A0, in);
/* acc += A1 * x[n-1] + A2 * x[n-2] */
vstate = __SIMD32_CONST(S->state);
acc = __SMLALD(S->A1, (q31_t) *vstate, acc);
#else
/* acc = A0 * x[n] */
acc = ((q31_t) S->A0) * in;
/* acc += A1 * x[n-1] + A2 * x[n-2] */
acc += (q31_t) S->A1 * S->state[0];
acc += (q31_t) S->A2 * S->state[1];
#endif
/* acc += y[n-1] */
acc += (q31_t) S->state[2] << 15;
/* saturate the output */
out = (q15_t) (__SSAT((acc >> 15), 16));
/* Update state */
S->state[1] = S->state[0];
S->state[0] = in;
S->state[2] = out;
/* return to application */
return (out);
}
/**
* @} end of PID group
*/
/**
* @brief Floating-point matrix inverse.
* @param[in] *src points to the instance of the input floating-point matrix structure.
* @param[out] *dst points to the instance of the output floating-point matrix structure.
* @return The function returns ARM_MATH_SIZE_MISMATCH, if the dimensions do not match.
* If the input matrix is singular (does not have an inverse), then the algorithm terminates and returns error status ARM_MATH_SINGULAR.
*/
arm_status arm_mat_inverse_f32(
const arm_matrix_instance_f32 * src,
arm_matrix_instance_f32 * dst);
/**
* @ingroup groupController
*/
/**
* @defgroup clarke Vector Clarke Transform
* Forward Clarke transform converts the instantaneous stator phases into a two-coordinate time invariant vector.
* Generally the Clarke transform uses three-phase currents Ia, Ib and Ic to calculate currents
* in the two-phase orthogonal stator axis Ialpha and Ibeta.
* When Ialpha is superposed with Ia as shown in the figure below
* \image html clarke.gif Stator current space vector and its components in (a,b).
* and Ia + Ib + Ic = 0, in this condition Ialpha and Ibeta
* can be calculated using only Ia and Ib.
*
* The function operates on a single sample of data and each call to the function returns the processed output.
* The library provides separate functions for Q31 and floating-point data types.
* \par Algorithm
* \image html clarkeFormula.gif
* where Ia and Ib are the instantaneous stator phases and
* pIalpha and pIbeta are the two coordinates of time invariant vector.
* \par Fixed-Point Behavior
* Care must be taken when using the Q31 version of the Clarke transform.
* In particular, the overflow and saturation behavior of the accumulator used must be considered.
* Refer to the function specific documentation below for usage guidelines.
*/
/**
* @addtogroup clarke
* @{
*/
/**
*
* @brief Floating-point Clarke transform
* @param[in] Ia input three-phase coordinate a
* @param[in] Ib input three-phase coordinate b
* @param[out] *pIalpha points to output two-phase orthogonal vector axis alpha
* @param[out] *pIbeta points to output two-phase orthogonal vector axis beta
* @return none.
*/
static __INLINE void arm_clarke_f32(
float32_t Ia,
float32_t Ib,
float32_t * pIalpha,
float32_t * pIbeta)
{
/* Calculate pIalpha using the equation, pIalpha = Ia */
*pIalpha = Ia;
/* Calculate pIbeta using the equation, pIbeta = (1/sqrt(3)) * Ia + (2/sqrt(3)) * Ib */
*pIbeta =
((float32_t) 0.57735026919 * Ia + (float32_t) 1.15470053838 * Ib);
}
/**
* @brief Clarke transform for Q31 version
* @param[in] Ia input three-phase coordinate a
* @param[in] Ib input three-phase coordinate b
* @param[out] *pIalpha points to output two-phase orthogonal vector axis alpha
* @param[out] *pIbeta points to output two-phase orthogonal vector axis beta
* @return none.
*
* Scaling and Overflow Behavior:
* \par
* The function is implemented using an internal 32-bit accumulator.
* The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
* There is saturation on the addition, hence there is no risk of overflow.
*/
static __INLINE void arm_clarke_q31(
q31_t Ia,
q31_t Ib,
q31_t * pIalpha,
q31_t * pIbeta)
{
q31_t product1, product2; /* Temporary variables used to store intermediate results */
/* Calculating pIalpha from Ia by equation pIalpha = Ia */
*pIalpha = Ia;
/* Intermediate product is calculated by (1/(sqrt(3)) * Ia) */
product1 = (q31_t) (((q63_t) Ia * 0x24F34E8B) >> 30);
/* Intermediate product is calculated by (2/sqrt(3) * Ib) */
product2 = (q31_t) (((q63_t) Ib * 0x49E69D16) >> 30);
/* pIbeta is calculated by adding the intermediate products */
*pIbeta = __QADD(product1, product2);
}
/**
* @} end of clarke group
*/
/**
* @brief Converts the elements of the Q7 vector to Q31 vector.
* @param[in] *pSrc input pointer
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_q7_to_q31(
q7_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @ingroup groupController
*/
/**
* @defgroup inv_clarke Vector Inverse Clarke Transform
* Inverse Clarke transform converts the two-coordinate time invariant vector into instantaneous stator phases.
*
* The function operates on a single sample of data and each call to the function returns the processed output.
* The library provides separate functions for Q31 and floating-point data types.
* \par Algorithm
* \image html clarkeInvFormula.gif
* where pIa and pIb are the instantaneous stator phases and
* Ialpha and Ibeta are the two coordinates of time invariant vector.
* \par Fixed-Point Behavior
* Care must be taken when using the Q31 version of the Clarke transform.
* In particular, the overflow and saturation behavior of the accumulator used must be considered.
* Refer to the function specific documentation below for usage guidelines.
*/
/**
* @addtogroup inv_clarke
* @{
*/
/**
* @brief Floating-point Inverse Clarke transform
* @param[in] Ialpha input two-phase orthogonal vector axis alpha
* @param[in] Ibeta input two-phase orthogonal vector axis beta
* @param[out] *pIa points to output three-phase coordinate a
* @param[out] *pIb points to output three-phase coordinate b
* @return none.
*/
static __INLINE void arm_inv_clarke_f32(
float32_t Ialpha,
float32_t Ibeta,
float32_t * pIa,
float32_t * pIb)
{
/* Calculating pIa from Ialpha by equation pIa = Ialpha */
*pIa = Ialpha;
/* Calculating pIb from Ialpha and Ibeta by equation pIb = -(1/2) * Ialpha + (sqrt(3)/2) * Ibeta */
*pIb = -0.5 * Ialpha + (float32_t) 0.8660254039 *Ibeta;
}
/**
* @brief Inverse Clarke transform for Q31 version
* @param[in] Ialpha input two-phase orthogonal vector axis alpha
* @param[in] Ibeta input two-phase orthogonal vector axis beta
* @param[out] *pIa points to output three-phase coordinate a
* @param[out] *pIb points to output three-phase coordinate b
* @return none.
*
* Scaling and Overflow Behavior:
* \par
* The function is implemented using an internal 32-bit accumulator.
* The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
* There is saturation on the subtraction, hence there is no risk of overflow.
*/
static __INLINE void arm_inv_clarke_q31(
q31_t Ialpha,
q31_t Ibeta,
q31_t * pIa,
q31_t * pIb)
{
q31_t product1, product2; /* Temporary variables used to store intermediate results */
/* Calculating pIa from Ialpha by equation pIa = Ialpha */
*pIa = Ialpha;
/* Intermediate product is calculated by (1/(2*sqrt(3)) * Ia) */
product1 = (q31_t) (((q63_t) (Ialpha) * (0x40000000)) >> 31);
/* Intermediate product is calculated by (1/sqrt(3) * pIb) */
product2 = (q31_t) (((q63_t) (Ibeta) * (0x6ED9EBA1)) >> 31);
/* pIb is calculated by subtracting the products */
*pIb = __QSUB(product2, product1);
}
/**
* @} end of inv_clarke group
*/
/**
* @brief Converts the elements of the Q7 vector to Q15 vector.
* @param[in] *pSrc input pointer
* @param[out] *pDst output pointer
* @param[in] blockSize number of samples to process
* @return none.
*/
void arm_q7_to_q15(
q7_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @ingroup groupController
*/
/**
* @defgroup park Vector Park Transform
*
* Forward Park transform converts the input two-coordinate vector to flux and torque components.
* The Park transform can be used to realize the transformation of the Ialpha and the Ibeta currents
* from the stationary to the moving reference frame and control the spatial relationship between
* the stator vector current and rotor flux vector.
* If we consider the d axis aligned with the rotor flux, the diagram below shows the
* current vector and the relationship from the two reference frames:
* \image html park.gif "Stator current space vector and its component in (a,b) and in the d,q rotating reference frame"
*
* The function operates on a single sample of data and each call to the function returns the processed output.
* The library provides separate functions for Q31 and floating-point data types.
* \par Algorithm
* \image html parkFormula.gif
* where Ialpha and Ibeta are the stator vector components,
* pId and pIq are rotor vector components and cosVal and sinVal are the
* cosine and sine values of theta (rotor flux position).
* \par Fixed-Point Behavior
* Care must be taken when using the Q31 version of the Park transform.
* In particular, the overflow and saturation behavior of the accumulator used must be considered.
* Refer to the function specific documentation below for usage guidelines.
*/
/**
* @addtogroup park
* @{
*/
/**
* @brief Floating-point Park transform
* @param[in] Ialpha input two-phase vector coordinate alpha
* @param[in] Ibeta input two-phase vector coordinate beta
* @param[out] *pId points to output rotor reference frame d
* @param[out] *pIq points to output rotor reference frame q
* @param[in] sinVal sine value of rotation angle theta
* @param[in] cosVal cosine value of rotation angle theta
* @return none.
*
* The function implements the forward Park transform.
*
*/
static __INLINE void arm_park_f32(
float32_t Ialpha,
float32_t Ibeta,
float32_t * pId,
float32_t * pIq,
float32_t sinVal,
float32_t cosVal)
{
/* Calculate pId using the equation, pId = Ialpha * cosVal + Ibeta * sinVal */
*pId = Ialpha * cosVal + Ibeta * sinVal;
/* Calculate pIq using the equation, pIq = - Ialpha * sinVal + Ibeta * cosVal */
*pIq = -Ialpha * sinVal + Ibeta * cosVal;
}
/**
* @brief Park transform for Q31 version
* @param[in] Ialpha input two-phase vector coordinate alpha
* @param[in] Ibeta input two-phase vector coordinate beta
* @param[out] *pId points to output rotor reference frame d
* @param[out] *pIq points to output rotor reference frame q
* @param[in] sinVal sine value of rotation angle theta
* @param[in] cosVal cosine value of rotation angle theta
* @return none.
*
* Scaling and Overflow Behavior:
* \par
* The function is implemented using an internal 32-bit accumulator.
* The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
* There is saturation on the addition and subtraction, hence there is no risk of overflow.
*/
static __INLINE void arm_park_q31(
q31_t Ialpha,
q31_t Ibeta,
q31_t * pId,
q31_t * pIq,
q31_t sinVal,
q31_t cosVal)
{
q31_t product1, product2; /* Temporary variables used to store intermediate results */
q31_t product3, product4; /* Temporary variables used to store intermediate results */
/* Intermediate product is calculated by (Ialpha * cosVal) */
product1 = (q31_t) (((q63_t) (Ialpha) * (cosVal)) >> 31);
/* Intermediate product is calculated by (Ibeta * sinVal) */
product2 = (q31_t) (((q63_t) (Ibeta) * (sinVal)) >> 31);
/* Intermediate product is calculated by (Ialpha * sinVal) */
product3 = (q31_t) (((q63_t) (Ialpha) * (sinVal)) >> 31);
/* Intermediate product is calculated by (Ibeta * cosVal) */
product4 = (q31_t) (((q63_t) (Ibeta) * (cosVal)) >> 31);
/* Calculate pId by adding the two intermediate products 1 and 2 */
*pId = __QADD(product1, product2);
/* Calculate pIq by subtracting the two intermediate products 3 from 4 */
*pIq = __QSUB(product4, product3);
}
/**
* @} end of park group
*/
/**
* @brief Converts the elements of the Q7 vector to floating-point vector.
* @param[in] *pSrc is input pointer
* @param[out] *pDst is output pointer
* @param[in] blockSize is the number of samples to process
* @return none.
*/
void arm_q7_to_float(
q7_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @ingroup groupController
*/
/**
* @defgroup inv_park Vector Inverse Park transform
* Inverse Park transform converts the input flux and torque components to two-coordinate vector.
*
* The function operates on a single sample of data and each call to the function returns the processed output.
* The library provides separate functions for Q31 and floating-point data types.
* \par Algorithm
* \image html parkInvFormula.gif
* where pIalpha and pIbeta are the stator vector components,
* Id and Iq are rotor vector components and cosVal and sinVal are the
* cosine and sine values of theta (rotor flux position).
* \par Fixed-Point Behavior
* Care must be taken when using the Q31 version of the Park transform.
* In particular, the overflow and saturation behavior of the accumulator used must be considered.
* Refer to the function specific documentation below for usage guidelines.
*/
/**
* @addtogroup inv_park
* @{
*/
/**
* @brief Floating-point Inverse Park transform
* @param[in] Id input coordinate of rotor reference frame d
* @param[in] Iq input coordinate of rotor reference frame q
* @param[out] *pIalpha points to output two-phase orthogonal vector axis alpha
* @param[out] *pIbeta points to output two-phase orthogonal vector axis beta
* @param[in] sinVal sine value of rotation angle theta
* @param[in] cosVal cosine value of rotation angle theta
* @return none.
*/
static __INLINE void arm_inv_park_f32(
float32_t Id,
float32_t Iq,
float32_t * pIalpha,
float32_t * pIbeta,
float32_t sinVal,
float32_t cosVal)
{
/* Calculate pIalpha using the equation, pIalpha = Id * cosVal - Iq * sinVal */
*pIalpha = Id * cosVal - Iq * sinVal;
/* Calculate pIbeta using the equation, pIbeta = Id * sinVal + Iq * cosVal */
*pIbeta = Id * sinVal + Iq * cosVal;
}
/**
* @brief Inverse Park transform for Q31 version
* @param[in] Id input coordinate of rotor reference frame d
* @param[in] Iq input coordinate of rotor reference frame q
* @param[out] *pIalpha points to output two-phase orthogonal vector axis alpha
* @param[out] *pIbeta points to output two-phase orthogonal vector axis beta
* @param[in] sinVal sine value of rotation angle theta
* @param[in] cosVal cosine value of rotation angle theta
* @return none.
*
* Scaling and Overflow Behavior:
* \par
* The function is implemented using an internal 32-bit accumulator.
* The accumulator maintains 1.31 format by truncating lower 31 bits of the intermediate multiplication in 2.62 format.
* There is saturation on the addition, hence there is no risk of overflow.
*/
static __INLINE void arm_inv_park_q31(
q31_t Id,
q31_t Iq,
q31_t * pIalpha,
q31_t * pIbeta,
q31_t sinVal,
q31_t cosVal)
{
q31_t product1, product2; /* Temporary variables used to store intermediate results */
q31_t product3, product4; /* Temporary variables used to store intermediate results */
/* Intermediate product is calculated by (Id * cosVal) */
product1 = (q31_t) (((q63_t) (Id) * (cosVal)) >> 31);
/* Intermediate product is calculated by (Iq * sinVal) */
product2 = (q31_t) (((q63_t) (Iq) * (sinVal)) >> 31);
/* Intermediate product is calculated by (Id * sinVal) */
product3 = (q31_t) (((q63_t) (Id) * (sinVal)) >> 31);
/* Intermediate product is calculated by (Iq * cosVal) */
product4 = (q31_t) (((q63_t) (Iq) * (cosVal)) >> 31);
/* Calculate pIalpha by using the two intermediate products 1 and 2 */
*pIalpha = __QSUB(product1, product2);
/* Calculate pIbeta by using the two intermediate products 3 and 4 */
*pIbeta = __QADD(product4, product3);
}
/**
* @} end of Inverse park group
*/
/**
* @brief Converts the elements of the Q31 vector to floating-point vector.
* @param[in] *pSrc is input pointer
* @param[out] *pDst is output pointer
* @param[in] blockSize is the number of samples to process
* @return none.
*/
void arm_q31_to_float(
q31_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @ingroup groupInterpolation
*/
/**
* @defgroup LinearInterpolate Linear Interpolation
*
* Linear interpolation is a method of curve fitting using linear polynomials.
* Linear interpolation works by effectively drawing a straight line between two neighboring samples and returning the appropriate point along that line
*
* \par
* \image html LinearInterp.gif "Linear interpolation"
*
* \par
* A Linear Interpolate function calculates an output value(y), for the input(x)
* using linear interpolation of the input values x0, x1( nearest input values) and the output values y0 and y1(nearest output values)
*
* \par Algorithm:
*
* y = y0 + (x - x0) * ((y1 - y0)/(x1-x0))
* where x0, x1 are nearest values of input x
* y0, y1 are nearest values to output y
*
*
* \par
* This set of functions implements Linear interpolation process
* for Q7, Q15, Q31, and floating-point data types. The functions operate on a single
* sample of data and each call to the function returns a single processed value.
* S points to an instance of the Linear Interpolate function data structure.
* x is the input sample value. The functions returns the output value.
*
* \par
* if x is outside of the table boundary, Linear interpolation returns first value of the table
* if x is below input range and returns last value of table if x is above range.
*/
/**
* @addtogroup LinearInterpolate
* @{
*/
/**
* @brief Process function for the floating-point Linear Interpolation Function.
* @param[in,out] *S is an instance of the floating-point Linear Interpolation structure
* @param[in] x input sample to process
* @return y processed output sample.
*
*/
static __INLINE float32_t arm_linear_interp_f32(
arm_linear_interp_instance_f32 * S,
float32_t x)
{
float32_t y;
float32_t x0, x1; /* Nearest input values */
float32_t y0, y1; /* Nearest output values */
float32_t xSpacing = S->xSpacing; /* spacing between input values */
int32_t i; /* Index variable */
float32_t *pYData = S->pYData; /* pointer to output table */
/* Calculation of index */
i = (int32_t) ((x - S->x1) / xSpacing);
if(i < 0)
{
/* Iniatilize output for below specified range as least output value of table */
y = pYData[0];
}
else if((uint32_t)i >= S->nValues)
{
/* Iniatilize output for above specified range as last output value of table */
y = pYData[S->nValues - 1];
}
else
{
/* Calculation of nearest input values */
x0 = S->x1 + i * xSpacing;
x1 = S->x1 + (i + 1) * xSpacing;
/* Read of nearest output values */
y0 = pYData[i];
y1 = pYData[i + 1];
/* Calculation of output */
y = y0 + (x - x0) * ((y1 - y0) / (x1 - x0));
}
/* returns output value */
return (y);
}
/**
*
* @brief Process function for the Q31 Linear Interpolation Function.
* @param[in] *pYData pointer to Q31 Linear Interpolation table
* @param[in] x input sample to process
* @param[in] nValues number of table values
* @return y processed output sample.
*
* \par
* Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part.
* This function can support maximum of table size 2^12.
*
*/
static __INLINE q31_t arm_linear_interp_q31(
q31_t * pYData,
q31_t x,
uint32_t nValues)
{
q31_t y; /* output */
q31_t y0, y1; /* Nearest output values */
q31_t fract; /* fractional part */
int32_t index; /* Index to read nearest output values */
/* Input is in 12.20 format */
/* 12 bits for the table index */
/* Index value calculation */
index = ((x & 0xFFF00000) >> 20);
if(index >= (int32_t)(nValues - 1))
{
return (pYData[nValues - 1]);
}
else if(index < 0)
{
return (pYData[0]);
}
else
{
/* 20 bits for the fractional part */
/* shift left by 11 to keep fract in 1.31 format */
fract = (x & 0x000FFFFF) << 11;
/* Read two nearest output values from the index in 1.31(q31) format */
y0 = pYData[index];
y1 = pYData[index + 1u];
/* Calculation of y0 * (1-fract) and y is in 2.30 format */
y = ((q31_t) ((q63_t) y0 * (0x7FFFFFFF - fract) >> 32));
/* Calculation of y0 * (1-fract) + y1 *fract and y is in 2.30 format */
y += ((q31_t) (((q63_t) y1 * fract) >> 32));
/* Convert y to 1.31 format */
return (y << 1u);
}
}
/**
*
* @brief Process function for the Q15 Linear Interpolation Function.
* @param[in] *pYData pointer to Q15 Linear Interpolation table
* @param[in] x input sample to process
* @param[in] nValues number of table values
* @return y processed output sample.
*
* \par
* Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part.
* This function can support maximum of table size 2^12.
*
*/
static __INLINE q15_t arm_linear_interp_q15(
q15_t * pYData,
q31_t x,
uint32_t nValues)
{
q63_t y; /* output */
q15_t y0, y1; /* Nearest output values */
q31_t fract; /* fractional part */
int32_t index; /* Index to read nearest output values */
/* Input is in 12.20 format */
/* 12 bits for the table index */
/* Index value calculation */
index = ((x & 0xFFF00000) >> 20u);
if(index >= (int32_t)(nValues - 1))
{
return (pYData[nValues - 1]);
}
else if(index < 0)
{
return (pYData[0]);
}
else
{
/* 20 bits for the fractional part */
/* fract is in 12.20 format */
fract = (x & 0x000FFFFF);
/* Read two nearest output values from the index */
y0 = pYData[index];
y1 = pYData[index + 1u];
/* Calculation of y0 * (1-fract) and y is in 13.35 format */
y = ((q63_t) y0 * (0xFFFFF - fract));
/* Calculation of (y0 * (1-fract) + y1 * fract) and y is in 13.35 format */
y += ((q63_t) y1 * (fract));
/* convert y to 1.15 format */
return (y >> 20);
}
}
/**
*
* @brief Process function for the Q7 Linear Interpolation Function.
* @param[in] *pYData pointer to Q7 Linear Interpolation table
* @param[in] x input sample to process
* @param[in] nValues number of table values
* @return y processed output sample.
*
* \par
* Input sample x is in 12.20 format which contains 12 bits for table index and 20 bits for fractional part.
* This function can support maximum of table size 2^12.
*/
static __INLINE q7_t arm_linear_interp_q7(
q7_t * pYData,
q31_t x,
uint32_t nValues)
{
q31_t y; /* output */
q7_t y0, y1; /* Nearest output values */
q31_t fract; /* fractional part */
uint32_t index; /* Index to read nearest output values */
/* Input is in 12.20 format */
/* 12 bits for the table index */
/* Index value calculation */
if (x < 0)
{
return (pYData[0]);
}
index = (x >> 20) & 0xfff;
if(index >= (nValues - 1))
{
return (pYData[nValues - 1]);
}
else
{
/* 20 bits for the fractional part */
/* fract is in 12.20 format */
fract = (x & 0x000FFFFF);
/* Read two nearest output values from the index and are in 1.7(q7) format */
y0 = pYData[index];
y1 = pYData[index + 1u];
/* Calculation of y0 * (1-fract ) and y is in 13.27(q27) format */
y = ((y0 * (0xFFFFF - fract)));
/* Calculation of y1 * fract + y0 * (1-fract) and y is in 13.27(q27) format */
y += (y1 * fract);
/* convert y to 1.7(q7) format */
return (y >> 20u);
}
}
/**
* @} end of LinearInterpolate group
*/
/**
* @brief Fast approximation to the trigonometric sine function for floating-point data.
* @param[in] x input value in radians.
* @return sin(x).
*/
float32_t arm_sin_f32(
float32_t x);
/**
* @brief Fast approximation to the trigonometric sine function for Q31 data.
* @param[in] x Scaled input value in radians.
* @return sin(x).
*/
q31_t arm_sin_q31(
q31_t x);
/**
* @brief Fast approximation to the trigonometric sine function for Q15 data.
* @param[in] x Scaled input value in radians.
* @return sin(x).
*/
q15_t arm_sin_q15(
q15_t x);
/**
* @brief Fast approximation to the trigonometric cosine function for floating-point data.
* @param[in] x input value in radians.
* @return cos(x).
*/
float32_t arm_cos_f32(
float32_t x);
/**
* @brief Fast approximation to the trigonometric cosine function for Q31 data.
* @param[in] x Scaled input value in radians.
* @return cos(x).
*/
q31_t arm_cos_q31(
q31_t x);
/**
* @brief Fast approximation to the trigonometric cosine function for Q15 data.
* @param[in] x Scaled input value in radians.
* @return cos(x).
*/
q15_t arm_cos_q15(
q15_t x);
/**
* @ingroup groupFastMath
*/
/**
* @defgroup SQRT Square Root
*
* Computes the square root of a number.
* There are separate functions for Q15, Q31, and floating-point data types.
* The square root function is computed using the Newton-Raphson algorithm.
* This is an iterative algorithm of the form:
*
* x1 = x0 - f(x0)/f'(x0)
*
* where x1 is the current estimate,
* x0 is the previous estimate, and
* f'(x0) is the derivative of f() evaluated at x0.
* For the square root function, the algorithm reduces to:
*
*/
/**
* @addtogroup SQRT
* @{
*/
/**
* @brief Floating-point square root function.
* @param[in] in input value.
* @param[out] *pOut square root of input value.
* @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if
* in is negative value and returns zero output for negative values.
*/
static __INLINE arm_status arm_sqrt_f32(
float32_t in,
float32_t * pOut)
{
if(in > 0)
{
// #if __FPU_USED
#if (__FPU_USED == 1) && defined ( __CC_ARM )
*pOut = __sqrtf(in);
#else
*pOut = sqrtf(in);
#endif
return (ARM_MATH_SUCCESS);
}
else
{
*pOut = 0.0f;
return (ARM_MATH_ARGUMENT_ERROR);
}
}
/**
* @brief Q31 square root function.
* @param[in] in input value. The range of the input value is [0 +1) or 0x00000000 to 0x7FFFFFFF.
* @param[out] *pOut square root of input value.
* @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if
* in is negative value and returns zero output for negative values.
*/
arm_status arm_sqrt_q31(
q31_t in,
q31_t * pOut);
/**
* @brief Q15 square root function.
* @param[in] in input value. The range of the input value is [0 +1) or 0x0000 to 0x7FFF.
* @param[out] *pOut square root of input value.
* @return The function returns ARM_MATH_SUCCESS if input value is positive value or ARM_MATH_ARGUMENT_ERROR if
* in is negative value and returns zero output for negative values.
*/
arm_status arm_sqrt_q15(
q15_t in,
q15_t * pOut);
/**
* @} end of SQRT group
*/
/**
* @brief floating-point Circular write function.
*/
static __INLINE void arm_circularWrite_f32(
int32_t * circBuffer,
int32_t L,
uint16_t * writeOffset,
int32_t bufferInc,
const int32_t * src,
int32_t srcInc,
uint32_t blockSize)
{
uint32_t i = 0u;
int32_t wOffset;
/* Copy the value of Index pointer that points
* to the current location where the input samples to be copied */
wOffset = *writeOffset;
/* Loop over the blockSize */
i = blockSize;
while(i > 0u)
{
/* copy the input sample to the circular buffer */
circBuffer[wOffset] = *src;
/* Update the input pointer */
src += srcInc;
/* Circularly update wOffset. Watch out for positive and negative value */
wOffset += bufferInc;
if(wOffset >= L)
wOffset -= L;
/* Decrement the loop counter */
i--;
}
/* Update the index pointer */
*writeOffset = wOffset;
}
/**
* @brief floating-point Circular Read function.
*/
static __INLINE void arm_circularRead_f32(
int32_t * circBuffer,
int32_t L,
int32_t * readOffset,
int32_t bufferInc,
int32_t * dst,
int32_t * dst_base,
int32_t dst_length,
int32_t dstInc,
uint32_t blockSize)
{
uint32_t i = 0u;
int32_t rOffset, dst_end;
/* Copy the value of Index pointer that points
* to the current location from where the input samples to be read */
rOffset = *readOffset;
dst_end = (int32_t) (dst_base + dst_length);
/* Loop over the blockSize */
i = blockSize;
while(i > 0u)
{
/* copy the sample from the circular buffer to the destination buffer */
*dst = circBuffer[rOffset];
/* Update the input pointer */
dst += dstInc;
if(dst == (int32_t *) dst_end)
{
dst = dst_base;
}
/* Circularly update rOffset. Watch out for positive and negative value */
rOffset += bufferInc;
if(rOffset >= L)
{
rOffset -= L;
}
/* Decrement the loop counter */
i--;
}
/* Update the index pointer */
*readOffset = rOffset;
}
/**
* @brief Q15 Circular write function.
*/
static __INLINE void arm_circularWrite_q15(
q15_t * circBuffer,
int32_t L,
uint16_t * writeOffset,
int32_t bufferInc,
const q15_t * src,
int32_t srcInc,
uint32_t blockSize)
{
uint32_t i = 0u;
int32_t wOffset;
/* Copy the value of Index pointer that points
* to the current location where the input samples to be copied */
wOffset = *writeOffset;
/* Loop over the blockSize */
i = blockSize;
while(i > 0u)
{
/* copy the input sample to the circular buffer */
circBuffer[wOffset] = *src;
/* Update the input pointer */
src += srcInc;
/* Circularly update wOffset. Watch out for positive and negative value */
wOffset += bufferInc;
if(wOffset >= L)
wOffset -= L;
/* Decrement the loop counter */
i--;
}
/* Update the index pointer */
*writeOffset = wOffset;
}
/**
* @brief Q15 Circular Read function.
*/
static __INLINE void arm_circularRead_q15(
q15_t * circBuffer,
int32_t L,
int32_t * readOffset,
int32_t bufferInc,
q15_t * dst,
q15_t * dst_base,
int32_t dst_length,
int32_t dstInc,
uint32_t blockSize)
{
uint32_t i = 0;
int32_t rOffset, dst_end;
/* Copy the value of Index pointer that points
* to the current location from where the input samples to be read */
rOffset = *readOffset;
dst_end = (int32_t) (dst_base + dst_length);
/* Loop over the blockSize */
i = blockSize;
while(i > 0u)
{
/* copy the sample from the circular buffer to the destination buffer */
*dst = circBuffer[rOffset];
/* Update the input pointer */
dst += dstInc;
if(dst == (q15_t *) dst_end)
{
dst = dst_base;
}
/* Circularly update wOffset. Watch out for positive and negative value */
rOffset += bufferInc;
if(rOffset >= L)
{
rOffset -= L;
}
/* Decrement the loop counter */
i--;
}
/* Update the index pointer */
*readOffset = rOffset;
}
/**
* @brief Q7 Circular write function.
*/
static __INLINE void arm_circularWrite_q7(
q7_t * circBuffer,
int32_t L,
uint16_t * writeOffset,
int32_t bufferInc,
const q7_t * src,
int32_t srcInc,
uint32_t blockSize)
{
uint32_t i = 0u;
int32_t wOffset;
/* Copy the value of Index pointer that points
* to the current location where the input samples to be copied */
wOffset = *writeOffset;
/* Loop over the blockSize */
i = blockSize;
while(i > 0u)
{
/* copy the input sample to the circular buffer */
circBuffer[wOffset] = *src;
/* Update the input pointer */
src += srcInc;
/* Circularly update wOffset. Watch out for positive and negative value */
wOffset += bufferInc;
if(wOffset >= L)
wOffset -= L;
/* Decrement the loop counter */
i--;
}
/* Update the index pointer */
*writeOffset = wOffset;
}
/**
* @brief Q7 Circular Read function.
*/
static __INLINE void arm_circularRead_q7(
q7_t * circBuffer,
int32_t L,
int32_t * readOffset,
int32_t bufferInc,
q7_t * dst,
q7_t * dst_base,
int32_t dst_length,
int32_t dstInc,
uint32_t blockSize)
{
uint32_t i = 0;
int32_t rOffset, dst_end;
/* Copy the value of Index pointer that points
* to the current location from where the input samples to be read */
rOffset = *readOffset;
dst_end = (int32_t) (dst_base + dst_length);
/* Loop over the blockSize */
i = blockSize;
while(i > 0u)
{
/* copy the sample from the circular buffer to the destination buffer */
*dst = circBuffer[rOffset];
/* Update the input pointer */
dst += dstInc;
if(dst == (q7_t *) dst_end)
{
dst = dst_base;
}
/* Circularly update rOffset. Watch out for positive and negative value */
rOffset += bufferInc;
if(rOffset >= L)
{
rOffset -= L;
}
/* Decrement the loop counter */
i--;
}
/* Update the index pointer */
*readOffset = rOffset;
}
/**
* @brief Sum of the squares of the elements of a Q31 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_power_q31(
q31_t * pSrc,
uint32_t blockSize,
q63_t * pResult);
/**
* @brief Sum of the squares of the elements of a floating-point vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_power_f32(
float32_t * pSrc,
uint32_t blockSize,
float32_t * pResult);
/**
* @brief Sum of the squares of the elements of a Q15 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_power_q15(
q15_t * pSrc,
uint32_t blockSize,
q63_t * pResult);
/**
* @brief Sum of the squares of the elements of a Q7 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_power_q7(
q7_t * pSrc,
uint32_t blockSize,
q31_t * pResult);
/**
* @brief Mean value of a Q7 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_mean_q7(
q7_t * pSrc,
uint32_t blockSize,
q7_t * pResult);
/**
* @brief Mean value of a Q15 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_mean_q15(
q15_t * pSrc,
uint32_t blockSize,
q15_t * pResult);
/**
* @brief Mean value of a Q31 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_mean_q31(
q31_t * pSrc,
uint32_t blockSize,
q31_t * pResult);
/**
* @brief Mean value of a floating-point vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_mean_f32(
float32_t * pSrc,
uint32_t blockSize,
float32_t * pResult);
/**
* @brief Variance of the elements of a floating-point vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_var_f32(
float32_t * pSrc,
uint32_t blockSize,
float32_t * pResult);
/**
* @brief Variance of the elements of a Q31 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_var_q31(
q31_t * pSrc,
uint32_t blockSize,
q31_t * pResult);
/**
* @brief Variance of the elements of a Q15 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_var_q15(
q15_t * pSrc,
uint32_t blockSize,
q15_t * pResult);
/**
* @brief Root Mean Square of the elements of a floating-point vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_rms_f32(
float32_t * pSrc,
uint32_t blockSize,
float32_t * pResult);
/**
* @brief Root Mean Square of the elements of a Q31 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_rms_q31(
q31_t * pSrc,
uint32_t blockSize,
q31_t * pResult);
/**
* @brief Root Mean Square of the elements of a Q15 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_rms_q15(
q15_t * pSrc,
uint32_t blockSize,
q15_t * pResult);
/**
* @brief Standard deviation of the elements of a floating-point vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_std_f32(
float32_t * pSrc,
uint32_t blockSize,
float32_t * pResult);
/**
* @brief Standard deviation of the elements of a Q31 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_std_q31(
q31_t * pSrc,
uint32_t blockSize,
q31_t * pResult);
/**
* @brief Standard deviation of the elements of a Q15 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output value.
* @return none.
*/
void arm_std_q15(
q15_t * pSrc,
uint32_t blockSize,
q15_t * pResult);
/**
* @brief Floating-point complex magnitude
* @param[in] *pSrc points to the complex input vector
* @param[out] *pDst points to the real output vector
* @param[in] numSamples number of complex samples in the input vector
* @return none.
*/
void arm_cmplx_mag_f32(
float32_t * pSrc,
float32_t * pDst,
uint32_t numSamples);
/**
* @brief Q31 complex magnitude
* @param[in] *pSrc points to the complex input vector
* @param[out] *pDst points to the real output vector
* @param[in] numSamples number of complex samples in the input vector
* @return none.
*/
void arm_cmplx_mag_q31(
q31_t * pSrc,
q31_t * pDst,
uint32_t numSamples);
/**
* @brief Q15 complex magnitude
* @param[in] *pSrc points to the complex input vector
* @param[out] *pDst points to the real output vector
* @param[in] numSamples number of complex samples in the input vector
* @return none.
*/
void arm_cmplx_mag_q15(
q15_t * pSrc,
q15_t * pDst,
uint32_t numSamples);
/**
* @brief Q15 complex dot product
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[in] numSamples number of complex samples in each vector
* @param[out] *realResult real part of the result returned here
* @param[out] *imagResult imaginary part of the result returned here
* @return none.
*/
void arm_cmplx_dot_prod_q15(
q15_t * pSrcA,
q15_t * pSrcB,
uint32_t numSamples,
q31_t * realResult,
q31_t * imagResult);
/**
* @brief Q31 complex dot product
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[in] numSamples number of complex samples in each vector
* @param[out] *realResult real part of the result returned here
* @param[out] *imagResult imaginary part of the result returned here
* @return none.
*/
void arm_cmplx_dot_prod_q31(
q31_t * pSrcA,
q31_t * pSrcB,
uint32_t numSamples,
q63_t * realResult,
q63_t * imagResult);
/**
* @brief Floating-point complex dot product
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[in] numSamples number of complex samples in each vector
* @param[out] *realResult real part of the result returned here
* @param[out] *imagResult imaginary part of the result returned here
* @return none.
*/
void arm_cmplx_dot_prod_f32(
float32_t * pSrcA,
float32_t * pSrcB,
uint32_t numSamples,
float32_t * realResult,
float32_t * imagResult);
/**
* @brief Q15 complex-by-real multiplication
* @param[in] *pSrcCmplx points to the complex input vector
* @param[in] *pSrcReal points to the real input vector
* @param[out] *pCmplxDst points to the complex output vector
* @param[in] numSamples number of samples in each vector
* @return none.
*/
void arm_cmplx_mult_real_q15(
q15_t * pSrcCmplx,
q15_t * pSrcReal,
q15_t * pCmplxDst,
uint32_t numSamples);
/**
* @brief Q31 complex-by-real multiplication
* @param[in] *pSrcCmplx points to the complex input vector
* @param[in] *pSrcReal points to the real input vector
* @param[out] *pCmplxDst points to the complex output vector
* @param[in] numSamples number of samples in each vector
* @return none.
*/
void arm_cmplx_mult_real_q31(
q31_t * pSrcCmplx,
q31_t * pSrcReal,
q31_t * pCmplxDst,
uint32_t numSamples);
/**
* @brief Floating-point complex-by-real multiplication
* @param[in] *pSrcCmplx points to the complex input vector
* @param[in] *pSrcReal points to the real input vector
* @param[out] *pCmplxDst points to the complex output vector
* @param[in] numSamples number of samples in each vector
* @return none.
*/
void arm_cmplx_mult_real_f32(
float32_t * pSrcCmplx,
float32_t * pSrcReal,
float32_t * pCmplxDst,
uint32_t numSamples);
/**
* @brief Minimum value of a Q7 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *result is output pointer
* @param[in] index is the array index of the minimum value in the input buffer.
* @return none.
*/
void arm_min_q7(
q7_t * pSrc,
uint32_t blockSize,
q7_t * result,
uint32_t * index);
/**
* @brief Minimum value of a Q15 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output pointer
* @param[in] *pIndex is the array index of the minimum value in the input buffer.
* @return none.
*/
void arm_min_q15(
q15_t * pSrc,
uint32_t blockSize,
q15_t * pResult,
uint32_t * pIndex);
/**
* @brief Minimum value of a Q31 vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output pointer
* @param[out] *pIndex is the array index of the minimum value in the input buffer.
* @return none.
*/
void arm_min_q31(
q31_t * pSrc,
uint32_t blockSize,
q31_t * pResult,
uint32_t * pIndex);
/**
* @brief Minimum value of a floating-point vector.
* @param[in] *pSrc is input pointer
* @param[in] blockSize is the number of samples to process
* @param[out] *pResult is output pointer
* @param[out] *pIndex is the array index of the minimum value in the input buffer.
* @return none.
*/
void arm_min_f32(
float32_t * pSrc,
uint32_t blockSize,
float32_t * pResult,
uint32_t * pIndex);
/**
* @brief Maximum value of a Q7 vector.
* @param[in] *pSrc points to the input buffer
* @param[in] blockSize length of the input vector
* @param[out] *pResult maximum value returned here
* @param[out] *pIndex index of maximum value returned here
* @return none.
*/
void arm_max_q7(
q7_t * pSrc,
uint32_t blockSize,
q7_t * pResult,
uint32_t * pIndex);
/**
* @brief Maximum value of a Q15 vector.
* @param[in] *pSrc points to the input buffer
* @param[in] blockSize length of the input vector
* @param[out] *pResult maximum value returned here
* @param[out] *pIndex index of maximum value returned here
* @return none.
*/
void arm_max_q15(
q15_t * pSrc,
uint32_t blockSize,
q15_t * pResult,
uint32_t * pIndex);
/**
* @brief Maximum value of a Q31 vector.
* @param[in] *pSrc points to the input buffer
* @param[in] blockSize length of the input vector
* @param[out] *pResult maximum value returned here
* @param[out] *pIndex index of maximum value returned here
* @return none.
*/
void arm_max_q31(
q31_t * pSrc,
uint32_t blockSize,
q31_t * pResult,
uint32_t * pIndex);
/**
* @brief Maximum value of a floating-point vector.
* @param[in] *pSrc points to the input buffer
* @param[in] blockSize length of the input vector
* @param[out] *pResult maximum value returned here
* @param[out] *pIndex index of maximum value returned here
* @return none.
*/
void arm_max_f32(
float32_t * pSrc,
uint32_t blockSize,
float32_t * pResult,
uint32_t * pIndex);
/**
* @brief Q15 complex-by-complex multiplication
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] numSamples number of complex samples in each vector
* @return none.
*/
void arm_cmplx_mult_cmplx_q15(
q15_t * pSrcA,
q15_t * pSrcB,
q15_t * pDst,
uint32_t numSamples);
/**
* @brief Q31 complex-by-complex multiplication
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] numSamples number of complex samples in each vector
* @return none.
*/
void arm_cmplx_mult_cmplx_q31(
q31_t * pSrcA,
q31_t * pSrcB,
q31_t * pDst,
uint32_t numSamples);
/**
* @brief Floating-point complex-by-complex multiplication
* @param[in] *pSrcA points to the first input vector
* @param[in] *pSrcB points to the second input vector
* @param[out] *pDst points to the output vector
* @param[in] numSamples number of complex samples in each vector
* @return none.
*/
void arm_cmplx_mult_cmplx_f32(
float32_t * pSrcA,
float32_t * pSrcB,
float32_t * pDst,
uint32_t numSamples);
/**
* @brief Converts the elements of the floating-point vector to Q31 vector.
* @param[in] *pSrc points to the floating-point input vector
* @param[out] *pDst points to the Q31 output vector
* @param[in] blockSize length of the input vector
* @return none.
*/
void arm_float_to_q31(
float32_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Converts the elements of the floating-point vector to Q15 vector.
* @param[in] *pSrc points to the floating-point input vector
* @param[out] *pDst points to the Q15 output vector
* @param[in] blockSize length of the input vector
* @return none
*/
void arm_float_to_q15(
float32_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Converts the elements of the floating-point vector to Q7 vector.
* @param[in] *pSrc points to the floating-point input vector
* @param[out] *pDst points to the Q7 output vector
* @param[in] blockSize length of the input vector
* @return none
*/
void arm_float_to_q7(
float32_t * pSrc,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Converts the elements of the Q31 vector to Q15 vector.
* @param[in] *pSrc is input pointer
* @param[out] *pDst is output pointer
* @param[in] blockSize is the number of samples to process
* @return none.
*/
void arm_q31_to_q15(
q31_t * pSrc,
q15_t * pDst,
uint32_t blockSize);
/**
* @brief Converts the elements of the Q31 vector to Q7 vector.
* @param[in] *pSrc is input pointer
* @param[out] *pDst is output pointer
* @param[in] blockSize is the number of samples to process
* @return none.
*/
void arm_q31_to_q7(
q31_t * pSrc,
q7_t * pDst,
uint32_t blockSize);
/**
* @brief Converts the elements of the Q15 vector to floating-point vector.
* @param[in] *pSrc is input pointer
* @param[out] *pDst is output pointer
* @param[in] blockSize is the number of samples to process
* @return none.
*/
void arm_q15_to_float(
q15_t * pSrc,
float32_t * pDst,
uint32_t blockSize);
/**
* @brief Converts the elements of the Q15 vector to Q31 vector.
* @param[in] *pSrc is input pointer
* @param[out] *pDst is output pointer
* @param[in] blockSize is the number of samples to process
* @return none.
*/
void arm_q15_to_q31(
q15_t * pSrc,
q31_t * pDst,
uint32_t blockSize);
/**
* @brief Converts the elements of the Q15 vector to Q7 vector.
* @param[in] *pSrc is input pointer
* @param[out] *pDst is output pointer
* @param[in] blockSize is the number of samples to process
* @return none.
*/
void arm_q15_to_q7(
q15_t * pSrc,
q7_t * pDst,
uint32_t blockSize);
/**
* @ingroup groupInterpolation
*/
/**
* @defgroup BilinearInterpolate Bilinear Interpolation
*
* Bilinear interpolation is an extension of linear interpolation applied to a two dimensional grid.
* The underlying function f(x, y) is sampled on a regular grid and the interpolation process
* determines values between the grid points.
* Bilinear interpolation is equivalent to two step linear interpolation, first in the x-dimension and then in the y-dimension.
* Bilinear interpolation is often used in image processing to rescale images.
* The CMSIS DSP library provides bilinear interpolation functions for Q7, Q15, Q31, and floating-point data types.
*
* Algorithm
* \par
* The instance structure used by the bilinear interpolation functions describes a two dimensional data table.
* For floating-point, the instance structure is defined as:
*
*
* \par
* where numRows specifies the number of rows in the table;
* numCols specifies the number of columns in the table;
* and pData points to an array of size numRows*numCols values.
* The data table pTable is organized in row order and the supplied data values fall on integer indexes.
* That is, table element (x,y) is located at pTable[x + y*numCols] where x and y are integers.
*
* \par
* Let (x, y) specify the desired interpolation point. Then define:
*
* XF = floor(x)
* YF = floor(y)
*
* \par
* The interpolated output point is computed as:
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_CAN_H
#define __STM32F10x_CAN_H
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpadded"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @addtogroup CAN
* @{
*/
/** @defgroup CAN_Exported_Types
* @{
*/
#define IS_CAN_ALL_PERIPH(PERIPH) (((PERIPH) == CAN1) || \
((PERIPH) == CAN2))
/**
* @brief CAN init structure definition
*/
typedef struct
{
uint16_t CAN_Prescaler; /*!< Specifies the length of a time quantum.
It ranges from 1 to 1024. */
uint8_t CAN_Mode; /*!< Specifies the CAN operating mode.
This parameter can be a value of
@ref CAN_operating_mode */
uint8_t CAN_SJW; /*!< Specifies the maximum number of time quanta
the CAN hardware is allowed to lengthen or
shorten a bit to perform resynchronization.
This parameter can be a value of
@ref CAN_synchronisation_jump_width */
uint8_t CAN_BS1; /*!< Specifies the number of time quanta in Bit
Segment 1. This parameter can be a value of
@ref CAN_time_quantum_in_bit_segment_1 */
uint8_t CAN_BS2; /*!< Specifies the number of time quanta in Bit
Segment 2.
This parameter can be a value of
@ref CAN_time_quantum_in_bit_segment_2 */
FunctionalState CAN_TTCM; /*!< Enable or disable the time triggered
communication mode. This parameter can be set
either to ENABLE or DISABLE. */
FunctionalState CAN_ABOM; /*!< Enable or disable the automatic bus-off
management. This parameter can be set either
to ENABLE or DISABLE. */
FunctionalState CAN_AWUM; /*!< Enable or disable the automatic wake-up mode.
This parameter can be set either to ENABLE or
DISABLE. */
FunctionalState CAN_NART; /*!< Enable or disable the no-automatic
retransmission mode. This parameter can be
set either to ENABLE or DISABLE. */
FunctionalState CAN_RFLM; /*!< Enable or disable the Receive FIFO Locked mode.
This parameter can be set either to ENABLE
or DISABLE. */
FunctionalState CAN_TXFP; /*!< Enable or disable the transmit FIFO priority.
This parameter can be set either to ENABLE
or DISABLE. */
} CAN_InitTypeDef;
/**
* @brief CAN filter init structure definition
*/
typedef struct
{
uint16_t CAN_FilterIdHigh; /*!< Specifies the filter identification number (MSBs for a 32-bit
configuration, first one for a 16-bit configuration).
This parameter can be a value between 0x0000 and 0xFFFF */
uint16_t CAN_FilterIdLow; /*!< Specifies the filter identification number (LSBs for a 32-bit
configuration, second one for a 16-bit configuration).
This parameter can be a value between 0x0000 and 0xFFFF */
uint16_t CAN_FilterMaskIdHigh; /*!< Specifies the filter mask number or identification number,
according to the mode (MSBs for a 32-bit configuration,
first one for a 16-bit configuration).
This parameter can be a value between 0x0000 and 0xFFFF */
uint16_t CAN_FilterMaskIdLow; /*!< Specifies the filter mask number or identification number,
according to the mode (LSBs for a 32-bit configuration,
second one for a 16-bit configuration).
This parameter can be a value between 0x0000 and 0xFFFF */
uint16_t CAN_FilterFIFOAssignment; /*!< Specifies the FIFO (0 or 1) which will be assigned to the filter.
This parameter can be a value of @ref CAN_filter_FIFO */
uint8_t CAN_FilterNumber; /*!< Specifies the filter which will be initialized. It ranges from 0 to 13. */
uint8_t CAN_FilterMode; /*!< Specifies the filter mode to be initialized.
This parameter can be a value of @ref CAN_filter_mode */
uint8_t CAN_FilterScale; /*!< Specifies the filter scale.
This parameter can be a value of @ref CAN_filter_scale */
FunctionalState CAN_FilterActivation; /*!< Enable or disable the filter.
This parameter can be set either to ENABLE or DISABLE. */
} CAN_FilterInitTypeDef;
/**
* @brief CAN Tx message structure definition
*/
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter can be a value between 0 to 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter can be a value between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< Specifies the type of identifier for the message that
will be transmitted. This parameter can be a value
of @ref CAN_identifier_type */
uint8_t RTR; /*!< Specifies the type of frame for the message that will
be transmitted. This parameter can be a value of
@ref CAN_remote_transmission_request */
uint8_t DLC; /*!< Specifies the length of the frame that will be
transmitted. This parameter can be a value between
0 to 8 */
uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0
to 0xFF. */
} CanTxMsg;
/**
* @brief CAN Rx message structure definition
*/
typedef struct
{
uint32_t StdId; /*!< Specifies the standard identifier.
This parameter can be a value between 0 to 0x7FF. */
uint32_t ExtId; /*!< Specifies the extended identifier.
This parameter can be a value between 0 to 0x1FFFFFFF. */
uint8_t IDE; /*!< Specifies the type of identifier for the message that
will be received. This parameter can be a value of
@ref CAN_identifier_type */
uint8_t RTR; /*!< Specifies the type of frame for the received message.
This parameter can be a value of
@ref CAN_remote_transmission_request */
uint8_t DLC; /*!< Specifies the length of the frame that will be received.
This parameter can be a value between 0 to 8 */
uint8_t Data[8]; /*!< Contains the data to be received. It ranges from 0 to
0xFF. */
uint8_t FMI; /*!< Specifies the index of the filter the message stored in
the mailbox passes through. This parameter can be a
value between 0 to 0xFF */
} CanRxMsg;
/**
* @}
*/
/** @defgroup CAN_Exported_Constants
* @{
*/
/** @defgroup CAN_sleep_constants
* @{
*/
#define CAN_InitStatus_Failed ((uint8_t)0x00) /*!< CAN initialization failed */
#define CAN_InitStatus_Success ((uint8_t)0x01) /*!< CAN initialization OK */
/**
* @}
*/
/** @defgroup CAN_Mode
* @{
*/
#define CAN_Mode_Normal ((uint8_t)0x00) /*!< normal mode */
#define CAN_Mode_LoopBack ((uint8_t)0x01) /*!< loopback mode */
#define CAN_Mode_Silent ((uint8_t)0x02) /*!< silent mode */
#define CAN_Mode_Silent_LoopBack ((uint8_t)0x03) /*!< loopback combined with silent mode */
#define IS_CAN_MODE(MODE) (((MODE) == CAN_Mode_Normal) || \
((MODE) == CAN_Mode_LoopBack)|| \
((MODE) == CAN_Mode_Silent) || \
((MODE) == CAN_Mode_Silent_LoopBack))
/**
* @}
*/
/**
* @defgroup CAN_Operating_Mode
* @{
*/
#define CAN_OperatingMode_Initialization ((uint8_t)0x00) /*!< Initialization mode */
#define CAN_OperatingMode_Normal ((uint8_t)0x01) /*!< Normal mode */
#define CAN_OperatingMode_Sleep ((uint8_t)0x02) /*!< sleep mode */
#define IS_CAN_OPERATING_MODE(MODE) (((MODE) == CAN_OperatingMode_Initialization) ||\
((MODE) == CAN_OperatingMode_Normal)|| \
((MODE) == CAN_OperatingMode_Sleep))
/**
* @}
*/
/**
* @defgroup CAN_Mode_Status
* @{
*/
#define CAN_ModeStatus_Failed ((uint8_t)0x00) /*!< CAN entering the specific mode failed */
#define CAN_ModeStatus_Success ((uint8_t)!CAN_ModeStatus_Failed) /*!< CAN entering the specific mode Succeed */
/**
* @}
*/
/** @defgroup CAN_synchronisation_jump_width
* @{
*/
#define CAN_SJW_1tq ((uint8_t)0x00) /*!< 1 time quantum */
#define CAN_SJW_2tq ((uint8_t)0x01) /*!< 2 time quantum */
#define CAN_SJW_3tq ((uint8_t)0x02) /*!< 3 time quantum */
#define CAN_SJW_4tq ((uint8_t)0x03) /*!< 4 time quantum */
#define IS_CAN_SJW(SJW) (((SJW) == CAN_SJW_1tq) || ((SJW) == CAN_SJW_2tq)|| \
((SJW) == CAN_SJW_3tq) || ((SJW) == CAN_SJW_4tq))
/**
* @}
*/
/** @defgroup CAN_time_quantum_in_bit_segment_1
* @{
*/
#define CAN_BS1_1tq ((uint8_t)0x00) /*!< 1 time quantum */
#define CAN_BS1_2tq ((uint8_t)0x01) /*!< 2 time quantum */
#define CAN_BS1_3tq ((uint8_t)0x02) /*!< 3 time quantum */
#define CAN_BS1_4tq ((uint8_t)0x03) /*!< 4 time quantum */
#define CAN_BS1_5tq ((uint8_t)0x04) /*!< 5 time quantum */
#define CAN_BS1_6tq ((uint8_t)0x05) /*!< 6 time quantum */
#define CAN_BS1_7tq ((uint8_t)0x06) /*!< 7 time quantum */
#define CAN_BS1_8tq ((uint8_t)0x07) /*!< 8 time quantum */
#define CAN_BS1_9tq ((uint8_t)0x08) /*!< 9 time quantum */
#define CAN_BS1_10tq ((uint8_t)0x09) /*!< 10 time quantum */
#define CAN_BS1_11tq ((uint8_t)0x0A) /*!< 11 time quantum */
#define CAN_BS1_12tq ((uint8_t)0x0B) /*!< 12 time quantum */
#define CAN_BS1_13tq ((uint8_t)0x0C) /*!< 13 time quantum */
#define CAN_BS1_14tq ((uint8_t)0x0D) /*!< 14 time quantum */
#define CAN_BS1_15tq ((uint8_t)0x0E) /*!< 15 time quantum */
#define CAN_BS1_16tq ((uint8_t)0x0F) /*!< 16 time quantum */
#define IS_CAN_BS1(BS1) ((BS1) <= CAN_BS1_16tq)
/**
* @}
*/
/** @defgroup CAN_time_quantum_in_bit_segment_2
* @{
*/
#define CAN_BS2_1tq ((uint8_t)0x00) /*!< 1 time quantum */
#define CAN_BS2_2tq ((uint8_t)0x01) /*!< 2 time quantum */
#define CAN_BS2_3tq ((uint8_t)0x02) /*!< 3 time quantum */
#define CAN_BS2_4tq ((uint8_t)0x03) /*!< 4 time quantum */
#define CAN_BS2_5tq ((uint8_t)0x04) /*!< 5 time quantum */
#define CAN_BS2_6tq ((uint8_t)0x05) /*!< 6 time quantum */
#define CAN_BS2_7tq ((uint8_t)0x06) /*!< 7 time quantum */
#define CAN_BS2_8tq ((uint8_t)0x07) /*!< 8 time quantum */
#define IS_CAN_BS2(BS2) ((BS2) <= CAN_BS2_8tq)
/**
* @}
*/
/** @defgroup CAN_clock_prescaler
* @{
*/
#define IS_CAN_PRESCALER(PRESCALER) (((PRESCALER) >= 1) && ((PRESCALER) <= 1024))
/**
* @}
*/
/** @defgroup CAN_filter_number
* @{
*/
#ifndef STM32F10X_CL
#define IS_CAN_FILTER_NUMBER(NUMBER) ((NUMBER) <= 13)
#else
#define IS_CAN_FILTER_NUMBER(NUMBER) ((NUMBER) <= 27)
#endif /* STM32F10X_CL */
/**
* @}
*/
/** @defgroup CAN_filter_mode
* @{
*/
#define CAN_FilterMode_IdMask ((uint8_t)0x00) /*!< identifier/mask mode */
#define CAN_FilterMode_IdList ((uint8_t)0x01) /*!< identifier list mode */
#define IS_CAN_FILTER_MODE(MODE) (((MODE) == CAN_FilterMode_IdMask) || \
((MODE) == CAN_FilterMode_IdList))
/**
* @}
*/
/** @defgroup CAN_filter_scale
* @{
*/
#define CAN_FilterScale_16bit ((uint8_t)0x00) /*!< Two 16-bit filters */
#define CAN_FilterScale_32bit ((uint8_t)0x01) /*!< One 32-bit filter */
#define IS_CAN_FILTER_SCALE(SCALE) (((SCALE) == CAN_FilterScale_16bit) || \
((SCALE) == CAN_FilterScale_32bit))
/**
* @}
*/
/** @defgroup CAN_filter_FIFO
* @{
*/
#define CAN_Filter_FIFO0 ((uint8_t)0x00) /*!< Filter FIFO 0 assignment for filter x */
#define CAN_Filter_FIFO1 ((uint8_t)0x01) /*!< Filter FIFO 1 assignment for filter x */
#define IS_CAN_FILTER_FIFO(FIFO) (((FIFO) == CAN_FilterFIFO0) || \
((FIFO) == CAN_FilterFIFO1))
/**
* @}
*/
/** @defgroup Start_bank_filter_for_slave_CAN
* @{
*/
#define IS_CAN_BANKNUMBER(BANKNUMBER) (((BANKNUMBER) >= 1) && ((BANKNUMBER) <= 27))
/**
* @}
*/
/** @defgroup CAN_Tx
* @{
*/
#define IS_CAN_TRANSMITMAILBOX(TRANSMITMAILBOX) ((TRANSMITMAILBOX) <= ((uint8_t)0x02))
#define IS_CAN_STDID(STDID) ((STDID) <= ((uint32_t)0x7FF))
#define IS_CAN_EXTID(EXTID) ((EXTID) <= ((uint32_t)0x1FFFFFFF))
#define IS_CAN_DLC(DLC) ((DLC) <= ((uint8_t)0x08))
/**
* @}
*/
/** @defgroup CAN_identifier_type
* @{
*/
#define CAN_Id_Standard ((uint32_t)0x00000000) /*!< Standard Id */
#define CAN_Id_Extended ((uint32_t)0x00000004) /*!< Extended Id */
#define IS_CAN_IDTYPE(IDTYPE) (((IDTYPE) == CAN_Id_Standard) || \
((IDTYPE) == CAN_Id_Extended))
/**
* @}
*/
/** @defgroup CAN_remote_transmission_request
* @{
*/
#define CAN_RTR_Data ((uint32_t)0x00000000) /*!< Data frame */
#define CAN_RTR_Remote ((uint32_t)0x00000002) /*!< Remote frame */
#define IS_CAN_RTR(RTR) (((RTR) == CAN_RTR_Data) || ((RTR) == CAN_RTR_Remote))
/**
* @}
*/
/** @defgroup CAN_transmit_constants
* @{
*/
#define CAN_TxStatus_Failed ((uint8_t)0x00)/*!< CAN transmission failed */
#define CAN_TxStatus_Ok ((uint8_t)0x01) /*!< CAN transmission succeeded */
#define CAN_TxStatus_Pending ((uint8_t)0x02) /*!< CAN transmission pending */
#define CAN_TxStatus_NoMailBox ((uint8_t)0x04) /*!< CAN cell did not provide an empty mailbox */
/**
* @}
*/
/** @defgroup CAN_receive_FIFO_number_constants
* @{
*/
#define CAN_FIFO0 ((uint8_t)0x00) /*!< CAN FIFO 0 used to receive */
#define CAN_FIFO1 ((uint8_t)0x01) /*!< CAN FIFO 1 used to receive */
#define IS_CAN_FIFO(FIFO) (((FIFO) == CAN_FIFO0) || ((FIFO) == CAN_FIFO1))
/**
* @}
*/
/** @defgroup CAN_sleep_constants
* @{
*/
#define CAN_Sleep_Failed ((uint8_t)0x00) /*!< CAN did not enter the sleep mode */
#define CAN_Sleep_Ok ((uint8_t)0x01) /*!< CAN entered the sleep mode */
/**
* @}
*/
/** @defgroup CAN_wake_up_constants
* @{
*/
#define CAN_WakeUp_Failed ((uint8_t)0x00) /*!< CAN did not leave the sleep mode */
#define CAN_WakeUp_Ok ((uint8_t)0x01) /*!< CAN leaved the sleep mode */
/**
* @}
*/
/**
* @defgroup CAN_Error_Code_constants
* @{
*/
#define CAN_ErrorCode_NoErr ((uint8_t)0x00) /*!< No Error */
#define CAN_ErrorCode_StuffErr ((uint8_t)0x10) /*!< Stuff Error */
#define CAN_ErrorCode_FormErr ((uint8_t)0x20) /*!< Form Error */
#define CAN_ErrorCode_ACKErr ((uint8_t)0x30) /*!< Acknowledgment Error */
#define CAN_ErrorCode_BitRecessiveErr ((uint8_t)0x40) /*!< Bit Recessive Error */
#define CAN_ErrorCode_BitDominantErr ((uint8_t)0x50) /*!< Bit Dominant Error */
#define CAN_ErrorCode_CRCErr ((uint8_t)0x60) /*!< CRC Error */
#define CAN_ErrorCode_SoftwareSetErr ((uint8_t)0x70) /*!< Software Set Error */
/**
* @}
*/
/** @defgroup CAN_flags
* @{
*/
/* If the flag is 0x3XXXXXXX, it means that it can be used with CAN_GetFlagStatus()
and CAN_ClearFlag() functions. */
/* If the flag is 0x1XXXXXXX, it means that it can only be used with CAN_GetFlagStatus() function. */
/* Transmit Flags */
#define CAN_FLAG_RQCP0 ((uint32_t)0x38000001) /*!< Request MailBox0 Flag */
#define CAN_FLAG_RQCP1 ((uint32_t)0x38000100) /*!< Request MailBox1 Flag */
#define CAN_FLAG_RQCP2 ((uint32_t)0x38010000) /*!< Request MailBox2 Flag */
/* Receive Flags */
#define CAN_FLAG_FMP0 ((uint32_t)0x12000003) /*!< FIFO 0 Message Pending Flag */
#define CAN_FLAG_FF0 ((uint32_t)0x32000008) /*!< FIFO 0 Full Flag */
#define CAN_FLAG_FOV0 ((uint32_t)0x32000010) /*!< FIFO 0 Overrun Flag */
#define CAN_FLAG_FMP1 ((uint32_t)0x14000003) /*!< FIFO 1 Message Pending Flag */
#define CAN_FLAG_FF1 ((uint32_t)0x34000008) /*!< FIFO 1 Full Flag */
#define CAN_FLAG_FOV1 ((uint32_t)0x34000010) /*!< FIFO 1 Overrun Flag */
/* Operating Mode Flags */
#define CAN_FLAG_WKU ((uint32_t)0x31000008) /*!< Wake up Flag */
#define CAN_FLAG_SLAK ((uint32_t)0x31000012) /*!< Sleep acknowledge Flag */
/* Note: When SLAK intterupt is disabled (SLKIE=0), no polling on SLAKI is possible.
In this case the SLAK bit can be polled.*/
/* Error Flags */
#define CAN_FLAG_EWG ((uint32_t)0x10F00001) /*!< Error Warning Flag */
#define CAN_FLAG_EPV ((uint32_t)0x10F00002) /*!< Error Passive Flag */
#define CAN_FLAG_BOF ((uint32_t)0x10F00004) /*!< Bus-Off Flag */
#define CAN_FLAG_LEC ((uint32_t)0x30F00070) /*!< Last error code Flag */
#define IS_CAN_GET_FLAG(FLAG) (((FLAG) == CAN_FLAG_LEC) || ((FLAG) == CAN_FLAG_BOF) || \
((FLAG) == CAN_FLAG_EPV) || ((FLAG) == CAN_FLAG_EWG) || \
((FLAG) == CAN_FLAG_WKU) || ((FLAG) == CAN_FLAG_FOV0) || \
((FLAG) == CAN_FLAG_FF0) || ((FLAG) == CAN_FLAG_FMP0) || \
((FLAG) == CAN_FLAG_FOV1) || ((FLAG) == CAN_FLAG_FF1) || \
((FLAG) == CAN_FLAG_FMP1) || ((FLAG) == CAN_FLAG_RQCP2) || \
((FLAG) == CAN_FLAG_RQCP1)|| ((FLAG) == CAN_FLAG_RQCP0) || \
((FLAG) == CAN_FLAG_SLAK ))
#define IS_CAN_CLEAR_FLAG(FLAG)(((FLAG) == CAN_FLAG_LEC) || ((FLAG) == CAN_FLAG_RQCP2) || \
((FLAG) == CAN_FLAG_RQCP1) || ((FLAG) == CAN_FLAG_RQCP0) || \
((FLAG) == CAN_FLAG_FF0) || ((FLAG) == CAN_FLAG_FOV0) ||\
((FLAG) == CAN_FLAG_FF1) || ((FLAG) == CAN_FLAG_FOV1) || \
((FLAG) == CAN_FLAG_WKU) || ((FLAG) == CAN_FLAG_SLAK))
/**
* @}
*/
/** @defgroup CAN_interrupts
* @{
*/
#define CAN_IT_TME ((uint32_t)0x00000001) /*!< Transmit mailbox empty Interrupt*/
/* Receive Interrupts */
#define CAN_IT_FMP0 ((uint32_t)0x00000002) /*!< FIFO 0 message pending Interrupt*/
#define CAN_IT_FF0 ((uint32_t)0x00000004) /*!< FIFO 0 full Interrupt*/
#define CAN_IT_FOV0 ((uint32_t)0x00000008) /*!< FIFO 0 overrun Interrupt*/
#define CAN_IT_FMP1 ((uint32_t)0x00000010) /*!< FIFO 1 message pending Interrupt*/
#define CAN_IT_FF1 ((uint32_t)0x00000020) /*!< FIFO 1 full Interrupt*/
#define CAN_IT_FOV1 ((uint32_t)0x00000040) /*!< FIFO 1 overrun Interrupt*/
/* Operating Mode Interrupts */
#define CAN_IT_WKU ((uint32_t)0x00010000) /*!< Wake-up Interrupt*/
#define CAN_IT_SLK ((uint32_t)0x00020000) /*!< Sleep acknowledge Interrupt*/
/* Error Interrupts */
#define CAN_IT_EWG ((uint32_t)0x00000100) /*!< Error warning Interrupt*/
#define CAN_IT_EPV ((uint32_t)0x00000200) /*!< Error passive Interrupt*/
#define CAN_IT_BOF ((uint32_t)0x00000400) /*!< Bus-off Interrupt*/
#define CAN_IT_LEC ((uint32_t)0x00000800) /*!< Last error code Interrupt*/
#define CAN_IT_ERR ((uint32_t)0x00008000) /*!< Error Interrupt*/
/* Flags named as Interrupts : kept only for FW compatibility */
#define CAN_IT_RQCP0 CAN_IT_TME
#define CAN_IT_RQCP1 CAN_IT_TME
#define CAN_IT_RQCP2 CAN_IT_TME
#define IS_CAN_IT(IT) (((IT) == CAN_IT_TME) || ((IT) == CAN_IT_FMP0) ||\
((IT) == CAN_IT_FF0) || ((IT) == CAN_IT_FOV0) ||\
((IT) == CAN_IT_FMP1) || ((IT) == CAN_IT_FF1) ||\
((IT) == CAN_IT_FOV1) || ((IT) == CAN_IT_EWG) ||\
((IT) == CAN_IT_EPV) || ((IT) == CAN_IT_BOF) ||\
((IT) == CAN_IT_LEC) || ((IT) == CAN_IT_ERR) ||\
((IT) == CAN_IT_WKU) || ((IT) == CAN_IT_SLK))
#define IS_CAN_CLEAR_IT(IT) (((IT) == CAN_IT_TME) || ((IT) == CAN_IT_FF0) ||\
((IT) == CAN_IT_FOV0)|| ((IT) == CAN_IT_FF1) ||\
((IT) == CAN_IT_FOV1)|| ((IT) == CAN_IT_EWG) ||\
((IT) == CAN_IT_EPV) || ((IT) == CAN_IT_BOF) ||\
((IT) == CAN_IT_LEC) || ((IT) == CAN_IT_ERR) ||\
((IT) == CAN_IT_WKU) || ((IT) == CAN_IT_SLK))
/**
* @}
*/
/** @defgroup CAN_Legacy
* @{
*/
#define CANINITFAILED CAN_InitStatus_Failed
#define CANINITOK CAN_InitStatus_Success
#define CAN_FilterFIFO0 CAN_Filter_FIFO0
#define CAN_FilterFIFO1 CAN_Filter_FIFO1
#define CAN_ID_STD CAN_Id_Standard
#define CAN_ID_EXT CAN_Id_Extended
#define CAN_RTR_DATA CAN_RTR_Data
#define CAN_RTR_REMOTE CAN_RTR_Remote
#define CANTXFAILE CAN_TxStatus_Failed
#define CANTXOK CAN_TxStatus_Ok
#define CANTXPENDING CAN_TxStatus_Pending
#define CAN_NO_MB CAN_TxStatus_NoMailBox
#define CANSLEEPFAILED CAN_Sleep_Failed
#define CANSLEEPOK CAN_Sleep_Ok
#define CANWAKEUPFAILED CAN_WakeUp_Failed
#define CANWAKEUPOK CAN_WakeUp_Ok
/**
* @}
*/
/**
* @}
*/
/** @defgroup CAN_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup CAN_Exported_Functions
* @{
*/
/* Function used to set the CAN configuration to the default reset state *****/
void CAN_DeInit(CAN_TypeDef* CANx);
/* Initialization and Configuration functions *********************************/
uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct);
void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct);
void CAN_StructInit(CAN_InitTypeDef* CAN_InitStruct);
void CAN_SlaveStartBank(uint8_t CAN_BankNumber);
void CAN_DBGFreeze(CAN_TypeDef* CANx, FunctionalState NewState);
void CAN_TTComModeCmd(CAN_TypeDef* CANx, FunctionalState NewState);
/* Transmit functions *********************************************************/
uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage);
uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox);
void CAN_CancelTransmit(CAN_TypeDef* CANx, uint8_t Mailbox);
/* Receive functions **********************************************************/
void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage);
void CAN_FIFORelease(CAN_TypeDef* CANx, uint8_t FIFONumber);
uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber);
/* Operation modes functions **************************************************/
uint8_t CAN_OperatingModeRequest(CAN_TypeDef* CANx, uint8_t CAN_OperatingMode);
uint8_t CAN_Sleep(CAN_TypeDef* CANx);
uint8_t CAN_WakeUp(CAN_TypeDef* CANx);
/* Error management functions *************************************************/
uint8_t CAN_GetLastErrorCode(CAN_TypeDef* CANx);
uint8_t CAN_GetReceiveErrorCounter(CAN_TypeDef* CANx);
uint8_t CAN_GetLSBTransmitErrorCounter(CAN_TypeDef* CANx);
/* Interrupts and flags management functions **********************************/
void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState NewState);
FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG);
void CAN_ClearFlag(CAN_TypeDef* CANx, uint32_t CAN_FLAG);
ITStatus CAN_GetITStatus(CAN_TypeDef* CANx, uint32_t CAN_IT);
void CAN_ClearITPendingBit(CAN_TypeDef* CANx, uint32_t CAN_IT);
#ifdef __cplusplus
}
#endif
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
#endif /* __STM32F10x_CAN_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/include/stm32f1-stdperiph/stm32f10x_cec.h
================================================
/**
******************************************************************************
* @file stm32f10x_cec.h
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file contains all the functions prototypes for the CEC firmware
* library.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_CRC_H
#define __STM32F10x_CRC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @addtogroup CRC
* @{
*/
/** @defgroup CRC_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup CRC_Exported_Constants
* @{
*/
/**
* @}
*/
/** @defgroup CRC_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup CRC_Exported_Functions
* @{
*/
void CRC_ResetDR(void);
uint32_t CRC_CalcCRC(uint32_t Data);
uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength);
uint32_t CRC_GetCRC(void);
void CRC_SetIDRegister(uint8_t IDValue);
uint8_t CRC_GetIDRegister(void);
#ifdef __cplusplus
}
#endif
#endif /* __STM32F10x_CRC_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/include/stm32f1-stdperiph/stm32f10x_dac.h
================================================
/**
******************************************************************************
* @file stm32f10x_dac.h
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file contains all the functions prototypes for the DAC firmware
* library.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_FSMC_H
#define __STM32F10x_FSMC_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @addtogroup FSMC
* @{
*/
/** @defgroup FSMC_Exported_Types
* @{
*/
/**
* @brief Timing parameters For NOR/SRAM Banks
*/
typedef struct
{
uint32_t FSMC_AddressSetupTime; /*!< Defines the number of HCLK cycles to configure
the duration of the address setup time.
This parameter can be a value between 0 and 0xF.
@note: It is not used with synchronous NOR Flash memories. */
uint32_t FSMC_AddressHoldTime; /*!< Defines the number of HCLK cycles to configure
the duration of the address hold time.
This parameter can be a value between 0 and 0xF.
@note: It is not used with synchronous NOR Flash memories.*/
uint32_t FSMC_DataSetupTime; /*!< Defines the number of HCLK cycles to configure
the duration of the data setup time.
This parameter can be a value between 0 and 0xFF.
@note: It is used for SRAMs, ROMs and asynchronous multiplexed NOR Flash memories. */
uint32_t FSMC_BusTurnAroundDuration; /*!< Defines the number of HCLK cycles to configure
the duration of the bus turnaround.
This parameter can be a value between 0 and 0xF.
@note: It is only used for multiplexed NOR Flash memories. */
uint32_t FSMC_CLKDivision; /*!< Defines the period of CLK clock output signal, expressed in number of HCLK cycles.
This parameter can be a value between 1 and 0xF.
@note: This parameter is not used for asynchronous NOR Flash, SRAM or ROM accesses. */
uint32_t FSMC_DataLatency; /*!< Defines the number of memory clock cycles to issue
to the memory before getting the first data.
The value of this parameter depends on the memory type as shown below:
- It must be set to 0 in case of a CRAM
- It is don't care in asynchronous NOR, SRAM or ROM accesses
- It may assume a value between 0 and 0xF in NOR Flash memories
with synchronous burst mode enable */
uint32_t FSMC_AccessMode; /*!< Specifies the asynchronous access mode.
This parameter can be a value of @ref FSMC_Access_Mode */
}FSMC_NORSRAMTimingInitTypeDef;
/**
* @brief FSMC NOR/SRAM Init structure definition
*/
typedef struct
{
uint32_t FSMC_Bank; /*!< Specifies the NOR/SRAM memory bank that will be used.
This parameter can be a value of @ref FSMC_NORSRAM_Bank */
uint32_t FSMC_DataAddressMux; /*!< Specifies whether the address and data values are
multiplexed on the databus or not.
This parameter can be a value of @ref FSMC_Data_Address_Bus_Multiplexing */
uint32_t FSMC_MemoryType; /*!< Specifies the type of external memory attached to
the corresponding memory bank.
This parameter can be a value of @ref FSMC_Memory_Type */
uint32_t FSMC_MemoryDataWidth; /*!< Specifies the external memory device width.
This parameter can be a value of @ref FSMC_Data_Width */
uint32_t FSMC_BurstAccessMode; /*!< Enables or disables the burst access mode for Flash memory,
valid only with synchronous burst Flash memories.
This parameter can be a value of @ref FSMC_Burst_Access_Mode */
uint32_t FSMC_AsynchronousWait; /*!< Enables or disables wait signal during asynchronous transfers,
valid only with asynchronous Flash memories.
This parameter can be a value of @ref FSMC_AsynchronousWait */
uint32_t FSMC_WaitSignalPolarity; /*!< Specifies the wait signal polarity, valid only when accessing
the Flash memory in burst mode.
This parameter can be a value of @ref FSMC_Wait_Signal_Polarity */
uint32_t FSMC_WrapMode; /*!< Enables or disables the Wrapped burst access mode for Flash
memory, valid only when accessing Flash memories in burst mode.
This parameter can be a value of @ref FSMC_Wrap_Mode */
uint32_t FSMC_WaitSignalActive; /*!< Specifies if the wait signal is asserted by the memory one
clock cycle before the wait state or during the wait state,
valid only when accessing memories in burst mode.
This parameter can be a value of @ref FSMC_Wait_Timing */
uint32_t FSMC_WriteOperation; /*!< Enables or disables the write operation in the selected bank by the FSMC.
This parameter can be a value of @ref FSMC_Write_Operation */
uint32_t FSMC_WaitSignal; /*!< Enables or disables the wait-state insertion via wait
signal, valid for Flash memory access in burst mode.
This parameter can be a value of @ref FSMC_Wait_Signal */
uint32_t FSMC_ExtendedMode; /*!< Enables or disables the extended mode.
This parameter can be a value of @ref FSMC_Extended_Mode */
uint32_t FSMC_WriteBurst; /*!< Enables or disables the write burst operation.
This parameter can be a value of @ref FSMC_Write_Burst */
FSMC_NORSRAMTimingInitTypeDef* FSMC_ReadWriteTimingStruct; /*!< Timing Parameters for write and read access if the ExtendedMode is not used*/
FSMC_NORSRAMTimingInitTypeDef* FSMC_WriteTimingStruct; /*!< Timing Parameters for write access if the ExtendedMode is used*/
}FSMC_NORSRAMInitTypeDef;
/**
* @brief Timing parameters For FSMC NAND and PCCARD Banks
*/
typedef struct
{
uint32_t FSMC_SetupTime; /*!< Defines the number of HCLK cycles to setup address before
the command assertion for NAND-Flash read or write access
to common/Attribute or I/O memory space (depending on
the memory space timing to be configured).
This parameter can be a value between 0 and 0xFF.*/
uint32_t FSMC_WaitSetupTime; /*!< Defines the minimum number of HCLK cycles to assert the
command for NAND-Flash read or write access to
common/Attribute or I/O memory space (depending on the
memory space timing to be configured).
This parameter can be a number between 0x00 and 0xFF */
uint32_t FSMC_HoldSetupTime; /*!< Defines the number of HCLK clock cycles to hold address
(and data for write access) after the command deassertion
for NAND-Flash read or write access to common/Attribute
or I/O memory space (depending on the memory space timing
to be configured).
This parameter can be a number between 0x00 and 0xFF */
uint32_t FSMC_HiZSetupTime; /*!< Defines the number of HCLK clock cycles during which the
databus is kept in HiZ after the start of a NAND-Flash
write access to common/Attribute or I/O memory space (depending
on the memory space timing to be configured).
This parameter can be a number between 0x00 and 0xFF */
}FSMC_NAND_PCCARDTimingInitTypeDef;
/**
* @brief FSMC NAND Init structure definition
*/
typedef struct
{
uint32_t FSMC_Bank; /*!< Specifies the NAND memory bank that will be used.
This parameter can be a value of @ref FSMC_NAND_Bank */
uint32_t FSMC_Waitfeature; /*!< Enables or disables the Wait feature for the NAND Memory Bank.
This parameter can be any value of @ref FSMC_Wait_feature */
uint32_t FSMC_MemoryDataWidth; /*!< Specifies the external memory device width.
This parameter can be any value of @ref FSMC_Data_Width */
uint32_t FSMC_ECC; /*!< Enables or disables the ECC computation.
This parameter can be any value of @ref FSMC_ECC */
uint32_t FSMC_ECCPageSize; /*!< Defines the page size for the extended ECC.
This parameter can be any value of @ref FSMC_ECC_Page_Size */
uint32_t FSMC_TCLRSetupTime; /*!< Defines the number of HCLK cycles to configure the
delay between CLE low and RE low.
This parameter can be a value between 0 and 0xFF. */
uint32_t FSMC_TARSetupTime; /*!< Defines the number of HCLK cycles to configure the
delay between ALE low and RE low.
This parameter can be a number between 0x0 and 0xFF */
FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_CommonSpaceTimingStruct; /*!< FSMC Common Space Timing */
FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_AttributeSpaceTimingStruct; /*!< FSMC Attribute Space Timing */
}FSMC_NANDInitTypeDef;
/**
* @brief FSMC PCCARD Init structure definition
*/
typedef struct
{
uint32_t FSMC_Waitfeature; /*!< Enables or disables the Wait feature for the Memory Bank.
This parameter can be any value of @ref FSMC_Wait_feature */
uint32_t FSMC_TCLRSetupTime; /*!< Defines the number of HCLK cycles to configure the
delay between CLE low and RE low.
This parameter can be a value between 0 and 0xFF. */
uint32_t FSMC_TARSetupTime; /*!< Defines the number of HCLK cycles to configure the
delay between ALE low and RE low.
This parameter can be a number between 0x0 and 0xFF */
FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_CommonSpaceTimingStruct; /*!< FSMC Common Space Timing */
FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_AttributeSpaceTimingStruct; /*!< FSMC Attribute Space Timing */
FSMC_NAND_PCCARDTimingInitTypeDef* FSMC_IOSpaceTimingStruct; /*!< FSMC IO Space Timing */
}FSMC_PCCARDInitTypeDef;
/**
* @}
*/
/** @defgroup FSMC_Exported_Constants
* @{
*/
/** @defgroup FSMC_NORSRAM_Bank
* @{
*/
#define FSMC_Bank1_NORSRAM1 ((uint32_t)0x00000000)
#define FSMC_Bank1_NORSRAM2 ((uint32_t)0x00000002)
#define FSMC_Bank1_NORSRAM3 ((uint32_t)0x00000004)
#define FSMC_Bank1_NORSRAM4 ((uint32_t)0x00000006)
/**
* @}
*/
/** @defgroup FSMC_NAND_Bank
* @{
*/
#define FSMC_Bank2_NAND ((uint32_t)0x00000010)
#define FSMC_Bank3_NAND ((uint32_t)0x00000100)
/**
* @}
*/
/** @defgroup FSMC_PCCARD_Bank
* @{
*/
#define FSMC_Bank4_PCCARD ((uint32_t)0x00001000)
/**
* @}
*/
#define IS_FSMC_NORSRAM_BANK(BANK) (((BANK) == FSMC_Bank1_NORSRAM1) || \
((BANK) == FSMC_Bank1_NORSRAM2) || \
((BANK) == FSMC_Bank1_NORSRAM3) || \
((BANK) == FSMC_Bank1_NORSRAM4))
#define IS_FSMC_NAND_BANK(BANK) (((BANK) == FSMC_Bank2_NAND) || \
((BANK) == FSMC_Bank3_NAND))
#define IS_FSMC_GETFLAG_BANK(BANK) (((BANK) == FSMC_Bank2_NAND) || \
((BANK) == FSMC_Bank3_NAND) || \
((BANK) == FSMC_Bank4_PCCARD))
#define IS_FSMC_IT_BANK(BANK) (((BANK) == FSMC_Bank2_NAND) || \
((BANK) == FSMC_Bank3_NAND) || \
((BANK) == FSMC_Bank4_PCCARD))
/** @defgroup NOR_SRAM_Controller
* @{
*/
/** @defgroup FSMC_Data_Address_Bus_Multiplexing
* @{
*/
#define FSMC_DataAddressMux_Disable ((uint32_t)0x00000000)
#define FSMC_DataAddressMux_Enable ((uint32_t)0x00000002)
#define IS_FSMC_MUX(MUX) (((MUX) == FSMC_DataAddressMux_Disable) || \
((MUX) == FSMC_DataAddressMux_Enable))
/**
* @}
*/
/** @defgroup FSMC_Memory_Type
* @{
*/
#define FSMC_MemoryType_SRAM ((uint32_t)0x00000000)
#define FSMC_MemoryType_PSRAM ((uint32_t)0x00000004)
#define FSMC_MemoryType_NOR ((uint32_t)0x00000008)
#define IS_FSMC_MEMORY(MEMORY) (((MEMORY) == FSMC_MemoryType_SRAM) || \
((MEMORY) == FSMC_MemoryType_PSRAM)|| \
((MEMORY) == FSMC_MemoryType_NOR))
/**
* @}
*/
/** @defgroup FSMC_Data_Width
* @{
*/
#define FSMC_MemoryDataWidth_8b ((uint32_t)0x00000000)
#define FSMC_MemoryDataWidth_16b ((uint32_t)0x00000010)
#define IS_FSMC_MEMORY_WIDTH(WIDTH) (((WIDTH) == FSMC_MemoryDataWidth_8b) || \
((WIDTH) == FSMC_MemoryDataWidth_16b))
/**
* @}
*/
/** @defgroup FSMC_Burst_Access_Mode
* @{
*/
#define FSMC_BurstAccessMode_Disable ((uint32_t)0x00000000)
#define FSMC_BurstAccessMode_Enable ((uint32_t)0x00000100)
#define IS_FSMC_BURSTMODE(STATE) (((STATE) == FSMC_BurstAccessMode_Disable) || \
((STATE) == FSMC_BurstAccessMode_Enable))
/**
* @}
*/
/** @defgroup FSMC_AsynchronousWait
* @{
*/
#define FSMC_AsynchronousWait_Disable ((uint32_t)0x00000000)
#define FSMC_AsynchronousWait_Enable ((uint32_t)0x00008000)
#define IS_FSMC_ASYNWAIT(STATE) (((STATE) == FSMC_AsynchronousWait_Disable) || \
((STATE) == FSMC_AsynchronousWait_Enable))
/**
* @}
*/
/** @defgroup FSMC_Wait_Signal_Polarity
* @{
*/
#define FSMC_WaitSignalPolarity_Low ((uint32_t)0x00000000)
#define FSMC_WaitSignalPolarity_High ((uint32_t)0x00000200)
#define IS_FSMC_WAIT_POLARITY(POLARITY) (((POLARITY) == FSMC_WaitSignalPolarity_Low) || \
((POLARITY) == FSMC_WaitSignalPolarity_High))
/**
* @}
*/
/** @defgroup FSMC_Wrap_Mode
* @{
*/
#define FSMC_WrapMode_Disable ((uint32_t)0x00000000)
#define FSMC_WrapMode_Enable ((uint32_t)0x00000400)
#define IS_FSMC_WRAP_MODE(MODE) (((MODE) == FSMC_WrapMode_Disable) || \
((MODE) == FSMC_WrapMode_Enable))
/**
* @}
*/
/** @defgroup FSMC_Wait_Timing
* @{
*/
#define FSMC_WaitSignalActive_BeforeWaitState ((uint32_t)0x00000000)
#define FSMC_WaitSignalActive_DuringWaitState ((uint32_t)0x00000800)
#define IS_FSMC_WAIT_SIGNAL_ACTIVE(ACTIVE) (((ACTIVE) == FSMC_WaitSignalActive_BeforeWaitState) || \
((ACTIVE) == FSMC_WaitSignalActive_DuringWaitState))
/**
* @}
*/
/** @defgroup FSMC_Write_Operation
* @{
*/
#define FSMC_WriteOperation_Disable ((uint32_t)0x00000000)
#define FSMC_WriteOperation_Enable ((uint32_t)0x00001000)
#define IS_FSMC_WRITE_OPERATION(OPERATION) (((OPERATION) == FSMC_WriteOperation_Disable) || \
((OPERATION) == FSMC_WriteOperation_Enable))
/**
* @}
*/
/** @defgroup FSMC_Wait_Signal
* @{
*/
#define FSMC_WaitSignal_Disable ((uint32_t)0x00000000)
#define FSMC_WaitSignal_Enable ((uint32_t)0x00002000)
#define IS_FSMC_WAITE_SIGNAL(SIGNAL) (((SIGNAL) == FSMC_WaitSignal_Disable) || \
((SIGNAL) == FSMC_WaitSignal_Enable))
/**
* @}
*/
/** @defgroup FSMC_Extended_Mode
* @{
*/
#define FSMC_ExtendedMode_Disable ((uint32_t)0x00000000)
#define FSMC_ExtendedMode_Enable ((uint32_t)0x00004000)
#define IS_FSMC_EXTENDED_MODE(MODE) (((MODE) == FSMC_ExtendedMode_Disable) || \
((MODE) == FSMC_ExtendedMode_Enable))
/**
* @}
*/
/** @defgroup FSMC_Write_Burst
* @{
*/
#define FSMC_WriteBurst_Disable ((uint32_t)0x00000000)
#define FSMC_WriteBurst_Enable ((uint32_t)0x00080000)
#define IS_FSMC_WRITE_BURST(BURST) (((BURST) == FSMC_WriteBurst_Disable) || \
((BURST) == FSMC_WriteBurst_Enable))
/**
* @}
*/
/** @defgroup FSMC_Address_Setup_Time
* @{
*/
#define IS_FSMC_ADDRESS_SETUP_TIME(TIME) ((TIME) <= 0xF)
/**
* @}
*/
/** @defgroup FSMC_Address_Hold_Time
* @{
*/
#define IS_FSMC_ADDRESS_HOLD_TIME(TIME) ((TIME) <= 0xF)
/**
* @}
*/
/** @defgroup FSMC_Data_Setup_Time
* @{
*/
#define IS_FSMC_DATASETUP_TIME(TIME) (((TIME) > 0) && ((TIME) <= 0xFF))
/**
* @}
*/
/** @defgroup FSMC_Bus_Turn_around_Duration
* @{
*/
#define IS_FSMC_TURNAROUND_TIME(TIME) ((TIME) <= 0xF)
/**
* @}
*/
/** @defgroup FSMC_CLK_Division
* @{
*/
#define IS_FSMC_CLK_DIV(DIV) ((DIV) <= 0xF)
/**
* @}
*/
/** @defgroup FSMC_Data_Latency
* @{
*/
#define IS_FSMC_DATA_LATENCY(LATENCY) ((LATENCY) <= 0xF)
/**
* @}
*/
/** @defgroup FSMC_Access_Mode
* @{
*/
#define FSMC_AccessMode_A ((uint32_t)0x00000000)
#define FSMC_AccessMode_B ((uint32_t)0x10000000)
#define FSMC_AccessMode_C ((uint32_t)0x20000000)
#define FSMC_AccessMode_D ((uint32_t)0x30000000)
#define IS_FSMC_ACCESS_MODE(MODE) (((MODE) == FSMC_AccessMode_A) || \
((MODE) == FSMC_AccessMode_B) || \
((MODE) == FSMC_AccessMode_C) || \
((MODE) == FSMC_AccessMode_D))
/**
* @}
*/
/**
* @}
*/
/** @defgroup NAND_PCCARD_Controller
* @{
*/
/** @defgroup FSMC_Wait_feature
* @{
*/
#define FSMC_Waitfeature_Disable ((uint32_t)0x00000000)
#define FSMC_Waitfeature_Enable ((uint32_t)0x00000002)
#define IS_FSMC_WAIT_FEATURE(FEATURE) (((FEATURE) == FSMC_Waitfeature_Disable) || \
((FEATURE) == FSMC_Waitfeature_Enable))
/**
* @}
*/
/** @defgroup FSMC_ECC
* @{
*/
#define FSMC_ECC_Disable ((uint32_t)0x00000000)
#define FSMC_ECC_Enable ((uint32_t)0x00000040)
#define IS_FSMC_ECC_STATE(STATE) (((STATE) == FSMC_ECC_Disable) || \
((STATE) == FSMC_ECC_Enable))
/**
* @}
*/
/** @defgroup FSMC_ECC_Page_Size
* @{
*/
#define FSMC_ECCPageSize_256Bytes ((uint32_t)0x00000000)
#define FSMC_ECCPageSize_512Bytes ((uint32_t)0x00020000)
#define FSMC_ECCPageSize_1024Bytes ((uint32_t)0x00040000)
#define FSMC_ECCPageSize_2048Bytes ((uint32_t)0x00060000)
#define FSMC_ECCPageSize_4096Bytes ((uint32_t)0x00080000)
#define FSMC_ECCPageSize_8192Bytes ((uint32_t)0x000A0000)
#define IS_FSMC_ECCPAGE_SIZE(SIZE) (((SIZE) == FSMC_ECCPageSize_256Bytes) || \
((SIZE) == FSMC_ECCPageSize_512Bytes) || \
((SIZE) == FSMC_ECCPageSize_1024Bytes) || \
((SIZE) == FSMC_ECCPageSize_2048Bytes) || \
((SIZE) == FSMC_ECCPageSize_4096Bytes) || \
((SIZE) == FSMC_ECCPageSize_8192Bytes))
/**
* @}
*/
/** @defgroup FSMC_TCLR_Setup_Time
* @{
*/
#define IS_FSMC_TCLR_TIME(TIME) ((TIME) <= 0xFF)
/**
* @}
*/
/** @defgroup FSMC_TAR_Setup_Time
* @{
*/
#define IS_FSMC_TAR_TIME(TIME) ((TIME) <= 0xFF)
/**
* @}
*/
/** @defgroup FSMC_Setup_Time
* @{
*/
#define IS_FSMC_SETUP_TIME(TIME) ((TIME) <= 0xFF)
/**
* @}
*/
/** @defgroup FSMC_Wait_Setup_Time
* @{
*/
#define IS_FSMC_WAIT_TIME(TIME) ((TIME) <= 0xFF)
/**
* @}
*/
/** @defgroup FSMC_Hold_Setup_Time
* @{
*/
#define IS_FSMC_HOLD_TIME(TIME) ((TIME) <= 0xFF)
/**
* @}
*/
/** @defgroup FSMC_HiZ_Setup_Time
* @{
*/
#define IS_FSMC_HIZ_TIME(TIME) ((TIME) <= 0xFF)
/**
* @}
*/
/** @defgroup FSMC_Interrupt_sources
* @{
*/
#define FSMC_IT_RisingEdge ((uint32_t)0x00000008)
#define FSMC_IT_Level ((uint32_t)0x00000010)
#define FSMC_IT_FallingEdge ((uint32_t)0x00000020)
#define IS_FSMC_IT(IT) ((((IT) & (uint32_t)0xFFFFFFC7) == 0x00000000) && ((IT) != 0x00000000))
#define IS_FSMC_GET_IT(IT) (((IT) == FSMC_IT_RisingEdge) || \
((IT) == FSMC_IT_Level) || \
((IT) == FSMC_IT_FallingEdge))
/**
* @}
*/
/** @defgroup FSMC_Flags
* @{
*/
#define FSMC_FLAG_RisingEdge ((uint32_t)0x00000001)
#define FSMC_FLAG_Level ((uint32_t)0x00000002)
#define FSMC_FLAG_FallingEdge ((uint32_t)0x00000004)
#define FSMC_FLAG_FEMPT ((uint32_t)0x00000040)
#define IS_FSMC_GET_FLAG(FLAG) (((FLAG) == FSMC_FLAG_RisingEdge) || \
((FLAG) == FSMC_FLAG_Level) || \
((FLAG) == FSMC_FLAG_FallingEdge) || \
((FLAG) == FSMC_FLAG_FEMPT))
#define IS_FSMC_CLEAR_FLAG(FLAG) ((((FLAG) & (uint32_t)0xFFFFFFF8) == 0x00000000) && ((FLAG) != 0x00000000))
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/** @defgroup FSMC_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup FSMC_Exported_Functions
* @{
*/
void FSMC_NORSRAMDeInit(uint32_t FSMC_Bank);
void FSMC_NANDDeInit(uint32_t FSMC_Bank);
void FSMC_PCCARDDeInit(void);
void FSMC_NORSRAMInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct);
void FSMC_NANDInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct);
void FSMC_PCCARDInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct);
void FSMC_NORSRAMStructInit(FSMC_NORSRAMInitTypeDef* FSMC_NORSRAMInitStruct);
void FSMC_NANDStructInit(FSMC_NANDInitTypeDef* FSMC_NANDInitStruct);
void FSMC_PCCARDStructInit(FSMC_PCCARDInitTypeDef* FSMC_PCCARDInitStruct);
void FSMC_NORSRAMCmd(uint32_t FSMC_Bank, FunctionalState NewState);
void FSMC_NANDCmd(uint32_t FSMC_Bank, FunctionalState NewState);
void FSMC_PCCARDCmd(FunctionalState NewState);
void FSMC_NANDECCCmd(uint32_t FSMC_Bank, FunctionalState NewState);
uint32_t FSMC_GetECC(uint32_t FSMC_Bank);
void FSMC_ITConfig(uint32_t FSMC_Bank, uint32_t FSMC_IT, FunctionalState NewState);
FlagStatus FSMC_GetFlagStatus(uint32_t FSMC_Bank, uint32_t FSMC_FLAG);
void FSMC_ClearFlag(uint32_t FSMC_Bank, uint32_t FSMC_FLAG);
ITStatus FSMC_GetITStatus(uint32_t FSMC_Bank, uint32_t FSMC_IT);
void FSMC_ClearITPendingBit(uint32_t FSMC_Bank, uint32_t FSMC_IT);
#ifdef __cplusplus
}
#endif
#endif /*__STM32F10x_FSMC_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/include/stm32f1-stdperiph/stm32f10x_gpio.h
================================================
/**
******************************************************************************
* @file stm32f10x_gpio.h
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file contains all the functions prototypes for the GPIO
* firmware library.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_I2C_H
#define __STM32F10x_I2C_H
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpadded"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @addtogroup I2C
* @{
*/
/** @defgroup I2C_Exported_Types
* @{
*/
/**
* @brief I2C Init structure definition
*/
typedef struct
{
uint32_t I2C_ClockSpeed; /*!< Specifies the clock frequency.
This parameter must be set to a value lower than 400kHz */
uint16_t I2C_Mode; /*!< Specifies the I2C mode.
This parameter can be a value of @ref I2C_mode */
uint16_t I2C_DutyCycle; /*!< Specifies the I2C fast mode duty cycle.
This parameter can be a value of @ref I2C_duty_cycle_in_fast_mode */
uint16_t I2C_OwnAddress1; /*!< Specifies the first device own address.
This parameter can be a 7-bit or 10-bit address. */
uint16_t I2C_Ack; /*!< Enables or disables the acknowledgement.
This parameter can be a value of @ref I2C_acknowledgement */
uint16_t I2C_AcknowledgedAddress; /*!< Specifies if 7-bit or 10-bit address is acknowledged.
This parameter can be a value of @ref I2C_acknowledged_address */
}I2C_InitTypeDef;
/**
* @}
*/
/** @defgroup I2C_Exported_Constants
* @{
*/
#define IS_I2C_ALL_PERIPH(PERIPH) (((PERIPH) == I2C1) || \
((PERIPH) == I2C2))
/** @defgroup I2C_mode
* @{
*/
#define I2C_Mode_I2C ((uint16_t)0x0000)
#define I2C_Mode_SMBusDevice ((uint16_t)0x0002)
#define I2C_Mode_SMBusHost ((uint16_t)0x000A)
#define IS_I2C_MODE(MODE) (((MODE) == I2C_Mode_I2C) || \
((MODE) == I2C_Mode_SMBusDevice) || \
((MODE) == I2C_Mode_SMBusHost))
/**
* @}
*/
/** @defgroup I2C_duty_cycle_in_fast_mode
* @{
*/
#define I2C_DutyCycle_16_9 ((uint16_t)0x4000) /*!< I2C fast mode Tlow/Thigh = 16/9 */
#define I2C_DutyCycle_2 ((uint16_t)0xBFFF) /*!< I2C fast mode Tlow/Thigh = 2 */
#define IS_I2C_DUTY_CYCLE(CYCLE) (((CYCLE) == I2C_DutyCycle_16_9) || \
((CYCLE) == I2C_DutyCycle_2))
/**
* @}
*/
/** @defgroup I2C_acknowledgement
* @{
*/
#define I2C_Ack_Enable ((uint16_t)0x0400)
#define I2C_Ack_Disable ((uint16_t)0x0000)
#define IS_I2C_ACK_STATE(STATE) (((STATE) == I2C_Ack_Enable) || \
((STATE) == I2C_Ack_Disable))
/**
* @}
*/
/** @defgroup I2C_transfer_direction
* @{
*/
#define I2C_Direction_Transmitter ((uint8_t)0x00)
#define I2C_Direction_Receiver ((uint8_t)0x01)
#define IS_I2C_DIRECTION(DIRECTION) (((DIRECTION) == I2C_Direction_Transmitter) || \
((DIRECTION) == I2C_Direction_Receiver))
/**
* @}
*/
/** @defgroup I2C_acknowledged_address
* @{
*/
#define I2C_AcknowledgedAddress_7bit ((uint16_t)0x4000)
#define I2C_AcknowledgedAddress_10bit ((uint16_t)0xC000)
#define IS_I2C_ACKNOWLEDGE_ADDRESS(ADDRESS) (((ADDRESS) == I2C_AcknowledgedAddress_7bit) || \
((ADDRESS) == I2C_AcknowledgedAddress_10bit))
/**
* @}
*/
/** @defgroup I2C_registers
* @{
*/
#define I2C_Register_CR1 ((uint8_t)0x00)
#define I2C_Register_CR2 ((uint8_t)0x04)
#define I2C_Register_OAR1 ((uint8_t)0x08)
#define I2C_Register_OAR2 ((uint8_t)0x0C)
#define I2C_Register_DR ((uint8_t)0x10)
#define I2C_Register_SR1 ((uint8_t)0x14)
#define I2C_Register_SR2 ((uint8_t)0x18)
#define I2C_Register_CCR ((uint8_t)0x1C)
#define I2C_Register_TRISE ((uint8_t)0x20)
#define IS_I2C_REGISTER(REGISTER) (((REGISTER) == I2C_Register_CR1) || \
((REGISTER) == I2C_Register_CR2) || \
((REGISTER) == I2C_Register_OAR1) || \
((REGISTER) == I2C_Register_OAR2) || \
((REGISTER) == I2C_Register_DR) || \
((REGISTER) == I2C_Register_SR1) || \
((REGISTER) == I2C_Register_SR2) || \
((REGISTER) == I2C_Register_CCR) || \
((REGISTER) == I2C_Register_TRISE))
/**
* @}
*/
/** @defgroup I2C_SMBus_alert_pin_level
* @{
*/
#define I2C_SMBusAlert_Low ((uint16_t)0x2000)
#define I2C_SMBusAlert_High ((uint16_t)0xDFFF)
#define IS_I2C_SMBUS_ALERT(ALERT) (((ALERT) == I2C_SMBusAlert_Low) || \
((ALERT) == I2C_SMBusAlert_High))
/**
* @}
*/
/** @defgroup I2C_PEC_position
* @{
*/
#define I2C_PECPosition_Next ((uint16_t)0x0800)
#define I2C_PECPosition_Current ((uint16_t)0xF7FF)
#define IS_I2C_PEC_POSITION(POSITION) (((POSITION) == I2C_PECPosition_Next) || \
((POSITION) == I2C_PECPosition_Current))
/**
* @}
*/
/** @defgroup I2C_NCAK_position
* @{
*/
#define I2C_NACKPosition_Next ((uint16_t)0x0800)
#define I2C_NACKPosition_Current ((uint16_t)0xF7FF)
#define IS_I2C_NACK_POSITION(POSITION) (((POSITION) == I2C_NACKPosition_Next) || \
((POSITION) == I2C_NACKPosition_Current))
/**
* @}
*/
/** @defgroup I2C_interrupts_definition
* @{
*/
#define I2C_IT_BUF ((uint16_t)0x0400)
#define I2C_IT_EVT ((uint16_t)0x0200)
#define I2C_IT_ERR ((uint16_t)0x0100)
#define IS_I2C_CONFIG_IT(IT) ((((IT) & (uint16_t)0xF8FF) == 0x00) && ((IT) != 0x00))
/**
* @}
*/
/** @defgroup I2C_interrupts_definition
* @{
*/
#define I2C_IT_SMBALERT ((uint32_t)0x01008000)
#define I2C_IT_TIMEOUT ((uint32_t)0x01004000)
#define I2C_IT_PECERR ((uint32_t)0x01001000)
#define I2C_IT_OVR ((uint32_t)0x01000800)
#define I2C_IT_AF ((uint32_t)0x01000400)
#define I2C_IT_ARLO ((uint32_t)0x01000200)
#define I2C_IT_BERR ((uint32_t)0x01000100)
#define I2C_IT_TXE ((uint32_t)0x06000080)
#define I2C_IT_RXNE ((uint32_t)0x06000040)
#define I2C_IT_STOPF ((uint32_t)0x02000010)
#define I2C_IT_ADD10 ((uint32_t)0x02000008)
#define I2C_IT_BTF ((uint32_t)0x02000004)
#define I2C_IT_ADDR ((uint32_t)0x02000002)
#define I2C_IT_SB ((uint32_t)0x02000001)
#define IS_I2C_CLEAR_IT(IT) ((((IT) & (uint16_t)0x20FF) == 0x00) && ((IT) != (uint16_t)0x00))
#define IS_I2C_GET_IT(IT) (((IT) == I2C_IT_SMBALERT) || ((IT) == I2C_IT_TIMEOUT) || \
((IT) == I2C_IT_PECERR) || ((IT) == I2C_IT_OVR) || \
((IT) == I2C_IT_AF) || ((IT) == I2C_IT_ARLO) || \
((IT) == I2C_IT_BERR) || ((IT) == I2C_IT_TXE) || \
((IT) == I2C_IT_RXNE) || ((IT) == I2C_IT_STOPF) || \
((IT) == I2C_IT_ADD10) || ((IT) == I2C_IT_BTF) || \
((IT) == I2C_IT_ADDR) || ((IT) == I2C_IT_SB))
/**
* @}
*/
/** @defgroup I2C_flags_definition
* @{
*/
/**
* @brief SR2 register flags
*/
#define I2C_FLAG_DUALF ((uint32_t)0x00800000)
#define I2C_FLAG_SMBHOST ((uint32_t)0x00400000)
#define I2C_FLAG_SMBDEFAULT ((uint32_t)0x00200000)
#define I2C_FLAG_GENCALL ((uint32_t)0x00100000)
#define I2C_FLAG_TRA ((uint32_t)0x00040000)
#define I2C_FLAG_BUSY ((uint32_t)0x00020000)
#define I2C_FLAG_MSL ((uint32_t)0x00010000)
/**
* @brief SR1 register flags
*/
#define I2C_FLAG_SMBALERT ((uint32_t)0x10008000)
#define I2C_FLAG_TIMEOUT ((uint32_t)0x10004000)
#define I2C_FLAG_PECERR ((uint32_t)0x10001000)
#define I2C_FLAG_OVR ((uint32_t)0x10000800)
#define I2C_FLAG_AF ((uint32_t)0x10000400)
#define I2C_FLAG_ARLO ((uint32_t)0x10000200)
#define I2C_FLAG_BERR ((uint32_t)0x10000100)
#define I2C_FLAG_TXE ((uint32_t)0x10000080)
#define I2C_FLAG_RXNE ((uint32_t)0x10000040)
#define I2C_FLAG_STOPF ((uint32_t)0x10000010)
#define I2C_FLAG_ADD10 ((uint32_t)0x10000008)
#define I2C_FLAG_BTF ((uint32_t)0x10000004)
#define I2C_FLAG_ADDR ((uint32_t)0x10000002)
#define I2C_FLAG_SB ((uint32_t)0x10000001)
#define IS_I2C_CLEAR_FLAG(FLAG) ((((FLAG) & (uint16_t)0x20FF) == 0x00) && ((FLAG) != (uint16_t)0x00))
#define IS_I2C_GET_FLAG(FLAG) (((FLAG) == I2C_FLAG_DUALF) || ((FLAG) == I2C_FLAG_SMBHOST) || \
((FLAG) == I2C_FLAG_SMBDEFAULT) || ((FLAG) == I2C_FLAG_GENCALL) || \
((FLAG) == I2C_FLAG_TRA) || ((FLAG) == I2C_FLAG_BUSY) || \
((FLAG) == I2C_FLAG_MSL) || ((FLAG) == I2C_FLAG_SMBALERT) || \
((FLAG) == I2C_FLAG_TIMEOUT) || ((FLAG) == I2C_FLAG_PECERR) || \
((FLAG) == I2C_FLAG_OVR) || ((FLAG) == I2C_FLAG_AF) || \
((FLAG) == I2C_FLAG_ARLO) || ((FLAG) == I2C_FLAG_BERR) || \
((FLAG) == I2C_FLAG_TXE) || ((FLAG) == I2C_FLAG_RXNE) || \
((FLAG) == I2C_FLAG_STOPF) || ((FLAG) == I2C_FLAG_ADD10) || \
((FLAG) == I2C_FLAG_BTF) || ((FLAG) == I2C_FLAG_ADDR) || \
((FLAG) == I2C_FLAG_SB))
/**
* @}
*/
/** @defgroup I2C_Events
* @{
*/
/*========================================
I2C Master Events (Events grouped in order of communication)
==========================================*/
/**
* @brief Communication start
*
* After sending the START condition (I2C_GenerateSTART() function) the master
* has to wait for this event. It means that the Start condition has been correctly
* released on the I2C bus (the bus is free, no other devices is communicating).
*
*/
/* --EV5 */
#define I2C_EVENT_MASTER_MODE_SELECT ((uint32_t)0x00030001) /* BUSY, MSL and SB flag */
/**
* @brief Address Acknowledge
*
* After checking on EV5 (start condition correctly released on the bus), the
* master sends the address of the slave(s) with which it will communicate
* (I2C_Send7bitAddress() function, it also determines the direction of the communication:
* Master transmitter or Receiver). Then the master has to wait that a slave acknowledges
* his address. If an acknowledge is sent on the bus, one of the following events will
* be set:
*
* 1) In case of Master Receiver (7-bit addressing): the I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED
* event is set.
*
* 2) In case of Master Transmitter (7-bit addressing): the I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED
* is set
*
* 3) In case of 10-Bit addressing mode, the master (just after generating the START
* and checking on EV5) has to send the header of 10-bit addressing mode (I2C_SendData()
* function). Then master should wait on EV9. It means that the 10-bit addressing
* header has been correctly sent on the bus. Then master should send the second part of
* the 10-bit address (LSB) using the function I2C_Send7bitAddress(). Then master
* should wait for event EV6.
*
*/
/* --EV6 */
#define I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED ((uint32_t)0x00070082) /* BUSY, MSL, ADDR, TXE and TRA flags */
#define I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED ((uint32_t)0x00030002) /* BUSY, MSL and ADDR flags */
/* --EV9 */
#define I2C_EVENT_MASTER_MODE_ADDRESS10 ((uint32_t)0x00030008) /* BUSY, MSL and ADD10 flags */
/**
* @brief Communication events
*
* If a communication is established (START condition generated and slave address
* acknowledged) then the master has to check on one of the following events for
* communication procedures:
*
* 1) Master Receiver mode: The master has to wait on the event EV7 then to read
* the data received from the slave (I2C_ReceiveData() function).
*
* 2) Master Transmitter mode: The master has to send data (I2C_SendData()
* function) then to wait on event EV8 or EV8_2.
* These two events are similar:
* - EV8 means that the data has been written in the data register and is
* being shifted out.
* - EV8_2 means that the data has been physically shifted out and output
* on the bus.
* In most cases, using EV8 is sufficient for the application.
* Using EV8_2 leads to a slower communication but ensure more reliable test.
* EV8_2 is also more suitable than EV8 for testing on the last data transmission
* (before Stop condition generation).
*
* @note In case the user software does not guarantee that this event EV7 is
* managed before the current byte end of transfer, then user may check on EV7
* and BTF flag at the same time (ie. (I2C_EVENT_MASTER_BYTE_RECEIVED | I2C_FLAG_BTF)).
* In this case the communication may be slower.
*
*/
/* Master RECEIVER mode -----------------------------*/
/* --EV7 */
#define I2C_EVENT_MASTER_BYTE_RECEIVED ((uint32_t)0x00030040) /* BUSY, MSL and RXNE flags */
/* Master TRANSMITTER mode --------------------------*/
/* --EV8 */
#define I2C_EVENT_MASTER_BYTE_TRANSMITTING ((uint32_t)0x00070080) /* TRA, BUSY, MSL, TXE flags */
/* --EV8_2 */
#define I2C_EVENT_MASTER_BYTE_TRANSMITTED ((uint32_t)0x00070084) /* TRA, BUSY, MSL, TXE and BTF flags */
/*========================================
I2C Slave Events (Events grouped in order of communication)
==========================================*/
/**
* @brief Communication start events
*
* Wait on one of these events at the start of the communication. It means that
* the I2C peripheral detected a Start condition on the bus (generated by master
* device) followed by the peripheral address. The peripheral generates an ACK
* condition on the bus (if the acknowledge feature is enabled through function
* I2C_AcknowledgeConfig()) and the events listed above are set :
*
* 1) In normal case (only one address managed by the slave), when the address
* sent by the master matches the own address of the peripheral (configured by
* I2C_OwnAddress1 field) the I2C_EVENT_SLAVE_XXX_ADDRESS_MATCHED event is set
* (where XXX could be TRANSMITTER or RECEIVER).
*
* 2) In case the address sent by the master matches the second address of the
* peripheral (configured by the function I2C_OwnAddress2Config() and enabled
* by the function I2C_DualAddressCmd()) the events I2C_EVENT_SLAVE_XXX_SECONDADDRESS_MATCHED
* (where XXX could be TRANSMITTER or RECEIVER) are set.
*
* 3) In case the address sent by the master is General Call (address 0x00) and
* if the General Call is enabled for the peripheral (using function I2C_GeneralCallCmd())
* the following event is set I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED.
*
*/
/* --EV1 (all the events below are variants of EV1) */
/* 1) Case of One Single Address managed by the slave */
#define I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED ((uint32_t)0x00020002) /* BUSY and ADDR flags */
#define I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED ((uint32_t)0x00060082) /* TRA, BUSY, TXE and ADDR flags */
/* 2) Case of Dual address managed by the slave */
#define I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED ((uint32_t)0x00820000) /* DUALF and BUSY flags */
#define I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED ((uint32_t)0x00860080) /* DUALF, TRA, BUSY and TXE flags */
/* 3) Case of General Call enabled for the slave */
#define I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED ((uint32_t)0x00120000) /* GENCALL and BUSY flags */
/**
* @brief Communication events
*
* Wait on one of these events when EV1 has already been checked and:
*
* - Slave RECEIVER mode:
* - EV2: When the application is expecting a data byte to be received.
* - EV4: When the application is expecting the end of the communication: master
* sends a stop condition and data transmission is stopped.
*
* - Slave Transmitter mode:
* - EV3: When a byte has been transmitted by the slave and the application is expecting
* the end of the byte transmission. The two events I2C_EVENT_SLAVE_BYTE_TRANSMITTED and
* I2C_EVENT_SLAVE_BYTE_TRANSMITTING are similar. The second one can optionally be
* used when the user software doesn't guarantee the EV3 is managed before the
* current byte end of transfer.
* - EV3_2: When the master sends a NACK in order to tell slave that data transmission
* shall end (before sending the STOP condition). In this case slave has to stop sending
* data bytes and expect a Stop condition on the bus.
*
* @note In case the user software does not guarantee that the event EV2 is
* managed before the current byte end of transfer, then user may check on EV2
* and BTF flag at the same time (ie. (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_BTF)).
* In this case the communication may be slower.
*
*/
/* Slave RECEIVER mode --------------------------*/
/* --EV2 */
#define I2C_EVENT_SLAVE_BYTE_RECEIVED ((uint32_t)0x00020040) /* BUSY and RXNE flags */
/* --EV4 */
#define I2C_EVENT_SLAVE_STOP_DETECTED ((uint32_t)0x00000010) /* STOPF flag */
/* Slave TRANSMITTER mode -----------------------*/
/* --EV3 */
#define I2C_EVENT_SLAVE_BYTE_TRANSMITTED ((uint32_t)0x00060084) /* TRA, BUSY, TXE and BTF flags */
#define I2C_EVENT_SLAVE_BYTE_TRANSMITTING ((uint32_t)0x00060080) /* TRA, BUSY and TXE flags */
/* --EV3_2 */
#define I2C_EVENT_SLAVE_ACK_FAILURE ((uint32_t)0x00000400) /* AF flag */
/*=========================== End of Events Description ==========================================*/
#define IS_I2C_EVENT(EVENT) (((EVENT) == I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED) || \
((EVENT) == I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED) || \
((EVENT) == I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED) || \
((EVENT) == I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED) || \
((EVENT) == I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED) || \
((EVENT) == I2C_EVENT_SLAVE_BYTE_RECEIVED) || \
((EVENT) == (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF)) || \
((EVENT) == (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL)) || \
((EVENT) == I2C_EVENT_SLAVE_BYTE_TRANSMITTED) || \
((EVENT) == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF)) || \
((EVENT) == (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL)) || \
((EVENT) == I2C_EVENT_SLAVE_STOP_DETECTED) || \
((EVENT) == I2C_EVENT_MASTER_MODE_SELECT) || \
((EVENT) == I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED) || \
((EVENT) == I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED) || \
((EVENT) == I2C_EVENT_MASTER_BYTE_RECEIVED) || \
((EVENT) == I2C_EVENT_MASTER_BYTE_TRANSMITTED) || \
((EVENT) == I2C_EVENT_MASTER_BYTE_TRANSMITTING) || \
((EVENT) == I2C_EVENT_MASTER_MODE_ADDRESS10) || \
((EVENT) == I2C_EVENT_SLAVE_ACK_FAILURE))
/**
* @}
*/
/** @defgroup I2C_own_address1
* @{
*/
#define IS_I2C_OWN_ADDRESS1(ADDRESS1) ((ADDRESS1) <= 0x3FF)
/**
* @}
*/
/** @defgroup I2C_clock_speed
* @{
*/
#define IS_I2C_CLOCK_SPEED(SPEED) (((SPEED) >= 0x1) && ((SPEED) <= 400000))
/**
* @}
*/
/**
* @}
*/
/** @defgroup I2C_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup I2C_Exported_Functions
* @{
*/
void I2C_DeInit(I2C_TypeDef* I2Cx);
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct);
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct);
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address);
void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState);
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data);
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx);
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction);
uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register);
void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition);
void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert);
void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition);
void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState);
uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx);
void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState);
void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle);
/**
* @brief
****************************************************************************************
*
* I2C State Monitoring Functions
*
****************************************************************************************
* This I2C driver provides three different ways for I2C state monitoring
* depending on the application requirements and constraints:
*
*
* 1) Basic state monitoring:
* Using I2C_CheckEvent() function:
* It compares the status registers (SR1 and SR2) content to a given event
* (can be the combination of one or more flags).
* It returns SUCCESS if the current status includes the given flags
* and returns ERROR if one or more flags are missing in the current status.
* - When to use:
* - This function is suitable for most applications as well as for startup
* activity since the events are fully described in the product reference manual
* (RM0008).
* - It is also suitable for users who need to define their own events.
* - Limitations:
* - If an error occurs (ie. error flags are set besides to the monitored flags),
* the I2C_CheckEvent() function may return SUCCESS despite the communication
* hold or corrupted real state.
* In this case, it is advised to use error interrupts to monitor the error
* events and handle them in the interrupt IRQ handler.
*
* @note
* For error management, it is advised to use the following functions:
* - I2C_ITConfig() to configure and enable the error interrupts (I2C_IT_ERR).
* - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs.
* Where x is the peripheral instance (I2C1, I2C2 ...)
* - I2C_GetFlagStatus() or I2C_GetITStatus() to be called into I2Cx_ER_IRQHandler()
* in order to determine which error occurred.
* - I2C_ClearFlag() or I2C_ClearITPendingBit() and/or I2C_SoftwareResetCmd()
* and/or I2C_GenerateStop() in order to clear the error flag and source,
* and return to correct communication status.
*
*
* 2) Advanced state monitoring:
* Using the function I2C_GetLastEvent() which returns the image of both status
* registers in a single word (uint32_t) (Status Register 2 value is shifted left
* by 16 bits and concatenated to Status Register 1).
* - When to use:
* - This function is suitable for the same applications above but it allows to
* overcome the limitations of I2C_GetFlagStatus() function (see below).
* The returned value could be compared to events already defined in the
* library (stm32f10x_i2c.h) or to custom values defined by user.
* - This function is suitable when multiple flags are monitored at the same time.
* - At the opposite of I2C_CheckEvent() function, this function allows user to
* choose when an event is accepted (when all events flags are set and no
* other flags are set or just when the needed flags are set like
* I2C_CheckEvent() function).
* - Limitations:
* - User may need to define his own events.
* - Same remark concerning the error management is applicable for this
* function if user decides to check only regular communication flags (and
* ignores error flags).
*
*
* 3) Flag-based state monitoring:
* Using the function I2C_GetFlagStatus() which simply returns the status of
* one single flag (ie. I2C_FLAG_RXNE ...).
* - When to use:
* - This function could be used for specific applications or in debug phase.
* - It is suitable when only one flag checking is needed (most I2C events
* are monitored through multiple flags).
* - Limitations:
* - When calling this function, the Status register is accessed. Some flags are
* cleared when the status register is accessed. So checking the status
* of one Flag, may clear other ones.
* - Function may need to be called twice or more in order to monitor one
* single event.
*
*/
/**
*
* 1) Basic state monitoring
*******************************************************************************
*/
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT);
/**
*
* 2) Advanced state monitoring
*******************************************************************************
*/
uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx);
/**
*
* 3) Flag-based state monitoring
*******************************************************************************
*/
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
/**
*
*******************************************************************************
*/
void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG);
ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT);
void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT);
#ifdef __cplusplus
}
#endif
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
#endif /*__STM32F10x_I2C_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/include/stm32f1-stdperiph/stm32f10x_iwdg.h
================================================
/**
******************************************************************************
* @file stm32f10x_iwdg.h
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file contains all the functions prototypes for the IWDG
* firmware library.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F10x_WWDG_H
#define __STM32F10x_WWDG_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @addtogroup WWDG
* @{
*/
/** @defgroup WWDG_Exported_Types
* @{
*/
/**
* @}
*/
/** @defgroup WWDG_Exported_Constants
* @{
*/
/** @defgroup WWDG_Prescaler
* @{
*/
#define WWDG_Prescaler_1 ((uint32_t)0x00000000)
#define WWDG_Prescaler_2 ((uint32_t)0x00000080)
#define WWDG_Prescaler_4 ((uint32_t)0x00000100)
#define WWDG_Prescaler_8 ((uint32_t)0x00000180)
#define IS_WWDG_PRESCALER(PRESCALER) (((PRESCALER) == WWDG_Prescaler_1) || \
((PRESCALER) == WWDG_Prescaler_2) || \
((PRESCALER) == WWDG_Prescaler_4) || \
((PRESCALER) == WWDG_Prescaler_8))
#define IS_WWDG_WINDOW_VALUE(VALUE) ((VALUE) <= 0x7F)
#define IS_WWDG_COUNTER(COUNTER) (((COUNTER) >= 0x40) && ((COUNTER) <= 0x7F))
/**
* @}
*/
/**
* @}
*/
/** @defgroup WWDG_Exported_Macros
* @{
*/
/**
* @}
*/
/** @defgroup WWDG_Exported_Functions
* @{
*/
void WWDG_DeInit(void);
void WWDG_SetPrescaler(uint32_t WWDG_Prescaler);
void WWDG_SetWindowValue(uint8_t WindowValue);
void WWDG_EnableIT(void);
void WWDG_SetCounter(uint8_t Counter);
void WWDG_Enable(uint8_t Counter);
FlagStatus WWDG_GetFlagStatus(void);
void WWDG_ClearFlag(void);
#ifdef __cplusplus
}
#endif
#endif /* __STM32F10x_WWDG_H */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/cmsis/README_DEVICE.txt
================================================
The system_stm32f10x.c file is from stsw-stm32054.zip, the folder:
STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x
The vectors_stm32f10x.c was created to conform to the startup_stm32f10x_xx*.s.
================================================
FILE: firmware/system/src/cmsis/system_stm32f10x.c
================================================
/**
******************************************************************************
* @file system_stm32f10x.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief CMSIS Cortex-M3 Device Peripheral Access Layer System Source File.
*
* 1. This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): Setups the system clock (System clock source, PLL Multiplier
* factors, AHB/APBx prescalers and Flash settings).
* This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32f10x_xx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
* by the user application to setup the SysTick
* timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
*
* 2. After each device reset the HSI (8 MHz) is used as system clock source.
* Then SystemInit() function is called, in "startup_stm32f10x_xx.s" file, to
* configure the system clock before to branch to main program.
*
* 3. If the system clock source selected by user fails to startup, the SystemInit()
* function will do nothing and HSI still used as system clock source. User can
* add some code to deal with this issue inside the SetSysClock() function.
*
* 4. The default value of HSE crystal is set to 8 MHz (or 25 MHz, depedning on
* the product used), refer to "HSE_VALUE" define in "stm32f10x.h" file.
* When HSE is used as system clock source, directly or through PLL, and you
* are using different crystal you have to adapt the HSE value to your own
* configuration.
*
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32f10x_system
* @{
*/
/** @addtogroup STM32F10x_System_Private_Includes
* @{
*/
#include "stm32f10x.h"
/**
* @}
*/
/** @addtogroup STM32F10x_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F10x_System_Private_Defines
* @{
*/
/*!< Uncomment the line corresponding to the desired System clock (SYSCLK)
frequency (after reset the HSI is used as SYSCLK source)
IMPORTANT NOTE:
==============
1. After each device reset the HSI is used as System clock source.
2. Please make sure that the selected System clock doesn't exceed your device's
maximum frequency.
3. If none of the define below is enabled, the HSI is used as System clock
source.
4. The System clock configuration functions provided within this file assume that:
- For Low, Medium and High density Value line devices an external 8MHz
crystal is used to drive the System clock.
- For Low, Medium and High density devices an external 8MHz crystal is
used to drive the System clock.
- For Connectivity line devices an external 25MHz crystal is used to drive
the System clock.
If you are using different crystal you have to adapt those functions accordingly.
*/
#if defined (STM32F10X_LD_VL) || (defined STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
#define SYSCLK_FREQ_24MHz 24000000
#else
/* #define SYSCLK_FREQ_HSE HSE_VALUE */
/* #define SYSCLK_FREQ_24MHz 24000000 */
/* #define SYSCLK_FREQ_36MHz 36000000 */
/* #define SYSCLK_FREQ_48MHz 48000000 */
/* #define SYSCLK_FREQ_56MHz 56000000 */
#define SYSCLK_FREQ_72MHz 72000000
#endif
/*!< Uncomment the following line if you need to use external SRAM mounted
on STM3210E-EVAL board (STM32 High density and XL-density devices) or on
STM32100E-EVAL board (STM32 High-density value line devices) as data memory */
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
/* #define DATA_IN_ExtSRAM */
#endif
/*!< Uncomment the following line if you need to relocate your vector Table in
Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x0 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
/**
* @}
*/
/** @addtogroup STM32F10x_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F10x_System_Private_Variables
* @{
*/
/*******************************************************************************
* Clock Definitions
*******************************************************************************/
#ifdef SYSCLK_FREQ_HSE
uint32_t SystemCoreClock = SYSCLK_FREQ_HSE; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_24MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_24MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_36MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_36MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_48MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_48MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_56MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_56MHz; /*!< System Clock Frequency (Core Clock) */
#elif defined SYSCLK_FREQ_72MHz
uint32_t SystemCoreClock = SYSCLK_FREQ_72MHz; /*!< System Clock Frequency (Core Clock) */
#else /*!< HSI Selected as System Clock source */
uint32_t SystemCoreClock = HSI_VALUE; /*!< System Clock Frequency (Core Clock) */
#endif
__I uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
/**
* @}
*/
/** @addtogroup STM32F10x_System_Private_FunctionPrototypes
* @{
*/
static void SetSysClock(void);
#ifdef SYSCLK_FREQ_HSE
static void SetSysClockToHSE(void);
#elif defined SYSCLK_FREQ_24MHz
static void SetSysClockTo24(void);
#elif defined SYSCLK_FREQ_36MHz
static void SetSysClockTo36(void);
#elif defined SYSCLK_FREQ_48MHz
static void SetSysClockTo48(void);
#elif defined SYSCLK_FREQ_56MHz
static void SetSysClockTo56(void);
#elif defined SYSCLK_FREQ_72MHz
static void SetSysClockTo72(void);
#endif
#ifdef DATA_IN_ExtSRAM
static void SystemInit_ExtMemCtl(void);
#endif /* DATA_IN_ExtSRAM */
/**
* @}
*/
/** @addtogroup STM32F10x_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system
* Initialize the Embedded Flash Interface, the PLL and update the
* SystemCoreClock variable.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
void SystemInit (void)
{
/* Reset the RCC clock configuration to the default reset state(for debug purpose) */
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
#ifdef STM32F10X_CL
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#else
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)
#ifdef DATA_IN_ExtSRAM
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM */
#endif
/* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */
/* Configure the Flash Latency cycles and enable prefetch buffer */
SetSysClock();
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */
#endif
}
/**
* @brief Update SystemCoreClock variable according to Clock Register Values.
* The SystemCoreClock variable contains the core clock (HCLK), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock (HCLK) changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
*
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
*
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
* or HSI_VALUE(*) multiplied by the PLL factors.
*
* (*) HSI_VALUE is a constant defined in stm32f1xx.h file (default value
* 8 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (**) HSE_VALUE is a constant defined in stm32f1xx.h file (default value
* 8 MHz or 25 MHz, depedning on the product used), user has to ensure
* that HSE_VALUE is same as the real frequency of the crystal used.
* Otherwise, this function may have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
* @param None
* @retval None
*/
void SystemCoreClockUpdate (void)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0;
#ifdef STM32F10X_CL
uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
#endif /* STM32F10X_CL */
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
uint32_t prediv1factor = 0;
#endif /* STM32F10X_LD_VL or STM32F10X_MD_VL or STM32F10X_HD_VL */
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp)
{
case 0x00: /* HSI used as system clock */
SystemCoreClock = HSI_VALUE;
break;
case 0x04: /* HSE used as system clock */
SystemCoreClock = HSE_VALUE;
break;
case 0x08: /* PLL used as system clock */
/* Get PLL clock source and multiplication factor ----------------------*/
pllmull = RCC->CFGR & RCC_CFGR_PLLMULL;
pllsource = RCC->CFGR & RCC_CFGR_PLLSRC;
#ifndef STM32F10X_CL
pllmull = ( pllmull >> 18) + 2;
if (pllsource == 0x00)
{
/* HSI oscillator clock divided by 2 selected as PLL clock entry */
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
}
else
{
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)
prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;
/* HSE oscillator clock selected as PREDIV1 clock entry */
SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;
#else
/* HSE selected as PLL clock entry */
if ((RCC->CFGR & RCC_CFGR_PLLXTPRE) != (uint32_t)RESET)
{/* HSE oscillator clock divided by 2 */
SystemCoreClock = (HSE_VALUE >> 1) * pllmull;
}
else
{
SystemCoreClock = HSE_VALUE * pllmull;
}
#endif
}
#else
pllmull = pllmull >> 18;
if (pllmull != 0x0D)
{
pllmull += 2;
}
else
{ /* PLL multiplication factor = PLL input clock * 6.5 */
pllmull = 13 / 2;
}
if (pllsource == 0x00)
{
/* HSI oscillator clock divided by 2 selected as PLL clock entry */
SystemCoreClock = (HSI_VALUE >> 1) * pllmull;
}
else
{/* PREDIV1 selected as PLL clock entry */
/* Get PREDIV1 clock source and division factor */
prediv1source = RCC->CFGR2 & RCC_CFGR2_PREDIV1SRC;
prediv1factor = (RCC->CFGR2 & RCC_CFGR2_PREDIV1) + 1;
if (prediv1source == 0)
{
/* HSE oscillator clock selected as PREDIV1 clock entry */
SystemCoreClock = (HSE_VALUE / prediv1factor) * pllmull;
}
else
{/* PLL2 clock selected as PREDIV1 clock entry */
/* Get PREDIV2 division factor and PLL2 multiplication factor */
prediv2factor = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> 4) + 1;
pll2mull = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> 8 ) + 2;
SystemCoreClock = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;
}
}
#endif /* STM32F10X_CL */
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
/* Compute HCLK clock frequency ----------------*/
/* Get HCLK prescaler */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
/* HCLK clock frequency */
SystemCoreClock >>= tmp;
}
/**
* @brief Configures the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers.
* @param None
* @retval None
*/
static void SetSysClock(void)
{
#ifdef SYSCLK_FREQ_HSE
SetSysClockToHSE();
#elif defined SYSCLK_FREQ_24MHz
SetSysClockTo24();
#elif defined SYSCLK_FREQ_36MHz
SetSysClockTo36();
#elif defined SYSCLK_FREQ_48MHz
SetSysClockTo48();
#elif defined SYSCLK_FREQ_56MHz
SetSysClockTo56();
#elif defined SYSCLK_FREQ_72MHz
SetSysClockTo72();
#endif
/* If none of the define above is enabled, the HSI is used as System clock
source (default after reset) */
}
/**
* @brief Setup the external memory controller. Called in startup_stm32f10x.s
* before jump to __main
* @param None
* @retval None
*/
#ifdef DATA_IN_ExtSRAM
/**
* @brief Setup the external memory controller.
* Called in startup_stm32f10x_xx.s/.c before jump to main.
* This function configures the external SRAM mounted on STM3210E-EVAL
* board (STM32 High density devices). This SRAM will be used as program
* data memory (including heap and stack).
* @param None
* @retval None
*/
void SystemInit_ExtMemCtl(void)
{
/*!< FSMC Bank1 NOR/SRAM3 is used for the STM3210E-EVAL, if another Bank is
required, then adjust the Register Addresses */
/* Enable FSMC clock */
RCC->AHBENR = 0x00000114;
/* Enable GPIOD, GPIOE, GPIOF and GPIOG clocks */
RCC->APB2ENR = 0x000001E0;
/* --------------- SRAM Data lines, NOE and NWE configuration ---------------*/
/*---------------- SRAM Address lines configuration -------------------------*/
/*---------------- NOE and NWE configuration --------------------------------*/
/*---------------- NE3 configuration ----------------------------------------*/
/*---------------- NBL0, NBL1 configuration ---------------------------------*/
GPIOD->CRL = 0x44BB44BB;
GPIOD->CRH = 0xBBBBBBBB;
GPIOE->CRL = 0xB44444BB;
GPIOE->CRH = 0xBBBBBBBB;
GPIOF->CRL = 0x44BBBBBB;
GPIOF->CRH = 0xBBBB4444;
GPIOG->CRL = 0x44BBBBBB;
GPIOG->CRH = 0x44444B44;
/*---------------- FSMC Configuration ---------------------------------------*/
/*---------------- Enable FSMC Bank1_SRAM Bank ------------------------------*/
FSMC_Bank1->BTCR[4] = 0x00001011;
FSMC_Bank1->BTCR[5] = 0x00000200;
}
#endif /* DATA_IN_ExtSRAM */
#ifdef SYSCLK_FREQ_HSE
/**
* @brief Selects HSE as System clock source and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockToHSE(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 0 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
#ifndef STM32F10X_CL
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
#else
if (HSE_VALUE <= 24000000)
{
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
}
else
{
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
}
#endif /* STM32F10X_CL */
#endif
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
/* Select HSE as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_HSE;
/* Wait till HSE is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x04)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
#elif defined SYSCLK_FREQ_24MHz
/**
* @brief Sets System clock frequency to 24MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo24(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
#if !defined STM32F10X_LD_VL && !defined STM32F10X_MD_VL && !defined STM32F10X_HD_VL
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 0 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_0;
#endif
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL configuration: PLLCLK = PREDIV1 * 6 = 24 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL6);
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
/* PLL configuration: = (HSE / 2) * 6 = 24 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_PREDIV1 | RCC_CFGR_PLLXTPRE_PREDIV1_Div2 | RCC_CFGR_PLLMULL6);
#else
/* PLL configuration: = (HSE / 2) * 6 = 24 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL6);
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
#elif defined SYSCLK_FREQ_36MHz
/**
* @brief Sets System clock frequency to 36MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo36(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 1 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV1;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 36 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
/*!< PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 10 = 4 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV10);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
#else
/* PLL configuration: PLLCLK = (HSE / 2) * 9 = 36 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLXTPRE_HSE_Div2 | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
#elif defined SYSCLK_FREQ_48MHz
/**
* @brief Sets System clock frequency to 48MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo48(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 1 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_1;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 6 = 48 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL6);
#else
/* PLL configuration: PLLCLK = HSE * 6 = 48 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL6);
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
#elif defined SYSCLK_FREQ_56MHz
/**
* @brief Sets System clock frequency to 56MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo56(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 7 = 56 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL7);
#else
/* PLL configuration: PLLCLK = HSE * 7 = 56 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL7);
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
#elif defined SYSCLK_FREQ_72MHz
/**
* @brief Sets System clock frequency to 72MHz and configure HCLK, PCLK2
* and PCLK1 prescalers.
* @note This function should be used only after reset.
* @param None
* @retval None
*/
static void SetSysClockTo72(void)
{
__IO uint32_t StartUpCounter = 0, HSEStatus = 0;
/* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/
/* Enable HSE */
RCC->CR |= ((uint32_t)RCC_CR_HSEON);
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;
} while((HSEStatus == 0) && (StartUpCounter != HSE_STARTUP_TIMEOUT));
if ((RCC->CR & RCC_CR_HSERDY) != RESET)
{
HSEStatus = (uint32_t)0x01;
}
else
{
HSEStatus = (uint32_t)0x00;
}
if (HSEStatus == (uint32_t)0x01)
{
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;
/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;
/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;
/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;
/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;
#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */
RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);
/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}
/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 |
RCC_CFGR_PLLMULL9);
#else
/* PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */
/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}
/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;
/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}
}
else
{ /* If HSE fails to start-up, the application will have wrong clock
configuration. User can add here some code to deal with this error */
}
}
#endif
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/cmsis/vectors_stm32f10x.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
#include "cortexm/ExceptionHandlers.h"
// ----------------------------------------------------------------------------
void __attribute__((weak))
Default_Handler(void);
// Forward declaration of the specific IRQ handlers. These are aliased
// to the Default_Handler, which is a 'forever' loop. When the application
// defines a handler (with the same name), this will automatically take
// precedence over these weak definitions
void __attribute__ ((weak, alias ("Default_Handler")))
WWDG_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
PVD_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TAMPER_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
RTC_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
FLASH_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
RCC_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
EXTI0_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
EXTI1_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
EXTI2_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
EXTI3_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
EXTI4_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA1_Channel1_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA1_Channel2_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA1_Channel3_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA1_Channel4_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA1_Channel5_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA1_Channel6_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA1_Channel7_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
ADC1_2_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
USB_HP_CAN1_TX_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
USB_LP_CAN1_RX0_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
CAN1_RX1_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
CAN1_SCE_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
EXTI9_5_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_BRK_TIM9_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_UP_TIM10_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_TRG_COM_TIM11_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_BRK_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_UP_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_TRG_COM_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_CC_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM2_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM3_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM4_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
I2C1_EV_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
I2C1_ER_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
I2C2_EV_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
I2C2_ER_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
SPI1_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
SPI2_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
USART1_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
USART2_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
USART3_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
EXTI15_10_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
RTCAlarm_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
USBWakeUp_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM8_BRK_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM8_UP_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM8_TRG_COM_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM8_BRK_TIM12_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM8_UP_TIM13_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM8_TRG_COM_TIM14_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM8_CC_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
ADC3_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
FSMC_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
SDIO_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM5_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
SPI3_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
UART4_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
UART5_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM6_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM7_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA2_Channel1_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA2_Channel2_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA2_Channel3_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA2_Channel4_5_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
CAN1_TX_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
CAN1_RX0_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
OTG_FS_WKUP_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA2_Channel4_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
DMA2_Channel5_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
ETH_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
ETH_WKUP_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
CAN2_TX_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
CAN2_RX0_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
CAN2_RX1_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
CAN2_SCE_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
OTG_FS_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_BRK_TIM15_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_UP_TIM16_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM1_TRG_COM_TIM17_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
CEC_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM6_DAC_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM12_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM13_IRQHandler(void);
void __attribute__ ((weak, alias ("Default_Handler")))
TIM14_IRQHandler(void);
// ----------------------------------------------------------------------------
extern unsigned int _estack;
typedef void
(* const pHandler)(void);
// ----------------------------------------------------------------------------
// The vector table.
// This relies on the linker script to place at correct location in memory.
__attribute__ ((section(".isr_vector")))
pHandler __isr_vectors[] =
{
// Core Level - CM3
(pHandler) &_estack, // The initial stack pointer
Reset_Handler, // The reset handler
NMI_Handler, // The NMI handler
HardFault_Handler, // The hard fault handler
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
MemManage_Handler, // The MPU fault handler
BusFault_Handler, // The bus fault handler
UsageFault_Handler, // The usage fault handler
#else
0, 0, 0, // Reserved
#endif
0, // Reserved
0, // Reserved
0, // Reserved
0, // Reserved
SVC_Handler, // SVCall handler
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
DebugMon_Handler, // Debug monitor handler
#else
0, // Reserved
#endif
0, // Reserved
PendSV_Handler, // The PendSV handler
SysTick_Handler, // The SysTick handler
// ----------------------------------------------------------------------
// Chip Level - STM32F10x
WWDG_IRQHandler, // Window WatchDog
PVD_IRQHandler, // PVD through EXTI Line detection
TAMPER_IRQHandler, // Tamper through the EXTI line
RTC_IRQHandler, // RTC Wakeup through the EXTI line
FLASH_IRQHandler, // FLASH
RCC_IRQHandler, // RCC
EXTI0_IRQHandler, // EXTI Line0
EXTI1_IRQHandler, // EXTI Line1
EXTI2_IRQHandler, // EXTI Line2
EXTI3_IRQHandler, // EXTI Line3
EXTI4_IRQHandler, // EXTI Line4
DMA1_Channel1_IRQHandler, // DMA1 Channel 1
DMA1_Channel2_IRQHandler, // DMA1 Channel 2
DMA1_Channel3_IRQHandler, // DMA1 Channel 3
DMA1_Channel4_IRQHandler, // DMA1 Channel 4
DMA1_Channel5_IRQHandler, // DMA1 Channel 5
DMA1_Channel6_IRQHandler, // DMA1 Channel 6
DMA1_Channel7_IRQHandler, // DMA1 Channel 7
ADC1_2_IRQHandler, // ADC1, ADC2
#if defined(STM32F10X_LD)
USB_HP_CAN1_TX_IRQHandler, //
USB_LP_CAN1_RX0_IRQHandler, //
CAN1_RX1_IRQHandler, //
CAN1_SCE_IRQHandler, //
EXTI9_5_IRQHandler, //
TIM1_BRK_IRQHandler, //
TIM1_UP_IRQHandler, //
TIM1_TRG_COM_IRQHandler, //
TIM1_CC_IRQHandler, //
TIM2_IRQHandler, //
TIM3_IRQHandler, //
0, //
I2C1_EV_IRQHandler, //
I2C1_ER_IRQHandler, //
0, //
0, //
SPI1_IRQHandler, //
0, //
USART1_IRQHandler, //
USART2_IRQHandler, //
0, //
EXTI15_10_IRQHandler, //
RTCAlarm_IRQHandler, //
USBWakeUp_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
// @0x108. This is for boot in RAM mode for STM32F10x Low Density devices.
(pHandler)0xF108F85F
#elif defined(STM32F10X_MD)
USB_HP_CAN1_TX_IRQHandler, //
USB_LP_CAN1_RX0_IRQHandler, //
CAN1_RX1_IRQHandler, //
CAN1_SCE_IRQHandler, //
EXTI9_5_IRQHandler, //
TIM1_BRK_IRQHandler, //
TIM1_UP_IRQHandler, //
TIM1_TRG_COM_IRQHandler, //
TIM1_CC_IRQHandler, //
TIM2_IRQHandler, //
TIM3_IRQHandler, //
TIM4_IRQHandler, //
I2C1_EV_IRQHandler, //
I2C1_ER_IRQHandler, //
I2C2_EV_IRQHandler, //
I2C2_ER_IRQHandler, //
SPI1_IRQHandler, //
SPI2_IRQHandler, //
USART1_IRQHandler, //
USART2_IRQHandler, //
USART3_IRQHandler, //
EXTI15_10_IRQHandler, //
RTCAlarm_IRQHandler, //
USBWakeUp_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
// @0x108. This is for boot in RAM mode for STM32F10x Low Density devices.
(pHandler)0xF108F85F
#elif defined(STM32F10X_HD)
USB_HP_CAN1_TX_IRQHandler, //
USB_LP_CAN1_RX0_IRQHandler, //
CAN1_RX1_IRQHandler, //
CAN1_SCE_IRQHandler, //
EXTI9_5_IRQHandler, //
TIM1_BRK_IRQHandler, //
TIM1_UP_IRQHandler, //
TIM1_TRG_COM_IRQHandler, //
TIM1_CC_IRQHandler, //
TIM2_IRQHandler, //
TIM3_IRQHandler, //
TIM4_IRQHandler, //
I2C1_EV_IRQHandler, //
I2C1_ER_IRQHandler, //
I2C2_EV_IRQHandler, //
I2C2_ER_IRQHandler, //
SPI1_IRQHandler, //
SPI2_IRQHandler, //
USART1_IRQHandler, //
USART2_IRQHandler, //
USART3_IRQHandler, //
EXTI15_10_IRQHandler, //
RTCAlarm_IRQHandler, //
USBWakeUp_IRQHandler, //
TIM8_BRK_IRQHandler, //
TIM8_UP_IRQHandler, //
TIM8_TRG_COM_IRQHandler, //
TIM8_CC_IRQHandler, //
ADC3_IRQHandler, //
FSMC_IRQHandler, //
SDIO_IRQHandler, //
TIM5_IRQHandler, //
SPI3_IRQHandler, //
UART4_IRQHandler, //
UART5_IRQHandler, //
TIM6_IRQHandler, //
TIM7_IRQHandler, //
DMA2_Channel1_IRQHandler, //
DMA2_Channel2_IRQHandler, //
DMA2_Channel3_IRQHandler, //
DMA2_Channel4_5_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
// @0x1E0. This is for boot in RAM mode for STM32F10x High Density devices.
(pHandler)0xF1E0F85F
#elif defined(STM32F10X_XL)
USB_HP_CAN1_TX_IRQHandler, //
USB_LP_CAN1_RX0_IRQHandler, //
CAN1_RX1_IRQHandler, //
CAN1_SCE_IRQHandler, //
EXTI9_5_IRQHandler, //
TIM1_BRK_TIM9_IRQHandler, //
TIM1_UP_TIM10_IRQHandler, //
TIM1_TRG_COM_TIM11_IRQHandler, //
TIM1_CC_IRQHandler, //
TIM2_IRQHandler, //
TIM3_IRQHandler, //
TIM4_IRQHandler, //
I2C1_EV_IRQHandler, //
I2C1_ER_IRQHandler, //
I2C2_EV_IRQHandler, //
I2C2_ER_IRQHandler, //
SPI1_IRQHandler, //
SPI2_IRQHandler, //
USART1_IRQHandler, //
USART2_IRQHandler, //
USART3_IRQHandler, //
EXTI15_10_IRQHandler, //
RTCAlarm_IRQHandler, //
USBWakeUp_IRQHandler, //
TIM8_BRK_TIM12_IRQHandler, //
TIM8_UP_TIM13_IRQHandler, //
TIM8_TRG_COM_TIM14_IRQHandler, //
TIM8_CC_IRQHandler, //
ADC3_IRQHandler, //
FSMC_IRQHandler, //
SDIO_IRQHandler, //
TIM5_IRQHandler, //
SPI3_IRQHandler, //
UART4_IRQHandler, //
UART5_IRQHandler, //
TIM6_IRQHandler, //
TIM7_IRQHandler, //
DMA2_Channel1_IRQHandler, //
DMA2_Channel2_IRQHandler, //
DMA2_Channel3_IRQHandler, //
DMA2_Channel4_5_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
// @0x1E0. This is for boot in RAM mode for STM32F10x Connectivity line Devices.
(pHandler)0xF1E0F85F
#elif defined(STM32F10X_CL)
CAN1_TX_IRQHandler, //
CAN1_RX0_IRQHandler, //
CAN1_RX1_IRQHandler, //
CAN1_SCE_IRQHandler, //
EXTI9_5_IRQHandler, //
TIM1_BRK_IRQHandler, //
TIM1_UP_IRQHandler, //
TIM1_TRG_COM_IRQHandler, //
TIM1_CC_IRQHandler, //
TIM2_IRQHandler, //
TIM3_IRQHandler, //
TIM4_IRQHandler, //
I2C1_EV_IRQHandler, //
I2C1_ER_IRQHandler, //
I2C2_EV_IRQHandler, //
I2C2_ER_IRQHandler, //
SPI1_IRQHandler, //
SPI2_IRQHandler, //
USART1_IRQHandler, //
USART2_IRQHandler, //
USART3_IRQHandler, //
EXTI15_10_IRQHandler, //
RTCAlarm_IRQHandler, //
OTG_FS_WKUP_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
TIM5_IRQHandler, //
SPI3_IRQHandler, //
UART4_IRQHandler, //
UART5_IRQHandler, //
TIM6_IRQHandler, //
TIM7_IRQHandler, //
DMA2_Channel1_IRQHandler, //
DMA2_Channel2_IRQHandler, //
DMA2_Channel3_IRQHandler, //
DMA2_Channel4_IRQHandler, //
DMA2_Channel5_IRQHandler, //
ETH_IRQHandler, //
ETH_WKUP_IRQHandler, //
CAN2_TX_IRQHandler, //
CAN2_RX0_IRQHandler, //
CAN2_RX1_IRQHandler, //
CAN2_SCE_IRQHandler, //
OTG_FS_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
// @0x1E0. This is for boot in RAM mode for STM32F10x Connectivity line Devices.
(pHandler)0xF1E0F85F
#elif defined(STM32F10X_LD_VL)
0, //
0, //
0, //
0, //
EXTI9_5_IRQHandler, //
TIM1_BRK_TIM15_IRQHandler, //
TIM1_UP_TIM16_IRQHandler, //
TIM1_TRG_COM_TIM17_IRQHandler, //
TIM1_CC_IRQHandler, //
TIM2_IRQHandler, //
TIM3_IRQHandler, //
0, //
I2C1_EV_IRQHandler, //
I2C1_ER_IRQHandler, //
0, //
0, //
SPI1_IRQHandler, //
0, //
USART1_IRQHandler, //
USART2_IRQHandler, //
0, //
EXTI15_10_IRQHandler, //
RTCAlarm_IRQHandler, //
CEC_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
TIM6_DAC_IRQHandler, //
TIM7_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
// @0x01CC. This is for boot in RAM mode for STM32F10x Low Density Value Line devices.
(pHandler)0xF108F85F
#elif defined(STM32F10X_MD_VL)
0, //
0, //
0, //
0, //
EXTI9_5_IRQHandler, //
TIM1_BRK_TIM15_IRQHandler, //
TIM1_UP_TIM16_IRQHandler, //
TIM1_TRG_COM_TIM17_IRQHandler, //
TIM1_CC_IRQHandler, //
TIM2_IRQHandler, //
TIM3_IRQHandler, //
TIM4_IRQHandler, //
I2C1_EV_IRQHandler, //
I2C1_ER_IRQHandler, //
I2C2_EV_IRQHandler, //
I2C2_ER_IRQHandler, //
SPI1_IRQHandler, //
SPI2_IRQHandler, //
USART1_IRQHandler, //
USART2_IRQHandler, //
USART3_IRQHandler, //
EXTI15_10_IRQHandler, //
RTCAlarm_IRQHandler, //
CEC_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
TIM6_DAC_IRQHandler, //
TIM7_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
// @0x01CC. This is for boot in RAM mode for STM32F10x Low Density Value Line devices.
(pHandler)0xF108F85F
#elif defined(STM32F10X_HD_VL)
0, //
0, //
0, //
0, //
EXTI9_5_IRQHandler, //
TIM1_BRK_TIM15_IRQHandler, //
TIM1_UP_TIM16_IRQHandler, //
TIM1_TRG_COM_TIM17_IRQHandler, //
TIM1_CC_IRQHandler, //
TIM2_IRQHandler, //
TIM3_IRQHandler, //
TIM4_IRQHandler, //
I2C1_EV_IRQHandler, //
I2C1_ER_IRQHandler, //
I2C2_EV_IRQHandler, //
I2C2_ER_IRQHandler, //
SPI1_IRQHandler, //
SPI2_IRQHandler, //
USART1_IRQHandler, //
USART2_IRQHandler, //
USART3_IRQHandler, //
EXTI15_10_IRQHandler, //
RTCAlarm_IRQHandler, //
CEC_IRQHandler, //
TIM12_IRQHandler, //
TIM13_IRQHandler, //
TIM14_IRQHandler, //
0, //
0, //
0, //
0, //
TIM5_IRQHandler, //
SPI3_IRQHandler, //
UART4_IRQHandler, //
UART5_IRQHandler, //
TIM6_DAC_IRQHandler, //
TIM7_IRQHandler, //
DMA2_Channel1_IRQHandler, //
DMA2_Channel2_IRQHandler, //
DMA2_Channel3_IRQHandler, //
DMA2_Channel4_5_IRQHandler, //
DMA2_Channel5_IRQHandler, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
0, //
// @0x1E0. This is for boot in RAM mode for STM32F10x High Density Value line devices.
(pHandler)0xF108F85F
#else
#error "missing vectors"
#endif
};
// ----------------------------------------------------------------------------
// Processor ends up here if an unexpected interrupt occurs or a specific
// handler is not present in the application code.
void __attribute__ ((section(".after_vectors")))
Default_Handler(void)
{
while (1)
{
}
}
// ----------------------------------------------------------------------------
================================================
FILE: firmware/system/src/cortexm/_initialize_hardware.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
#include "cmsis_device.h"
// ----------------------------------------------------------------------------
// Forward declarations.
void
__initialize_hardware(void);
// ----------------------------------------------------------------------------
// This is the default hardware initialisation routine, it can be
// redefined in the application for more complex applications that
// require early inits (before constructors), otherwise these can
// be done in main().
//
// Called early from _start(), right after data & bss init, before
// constructors.
//
// After Reset the Cortex-M processor is in Thread mode,
// priority is Privileged, and the Stack is set to Main.
void
__attribute__((weak))
__initialize_hardware(void)
{
// Call the CSMSIS system initialisation routine.
SystemInit();
#if defined (__VFP_FP__) && !defined (__SOFTFP__)
// Enable the Cortex-M4 FPU only when -mfloat-abi=hard.
// Code taken from Section 7.1, Cortex-M4 TRM (DDI0439C)
// Set bits 20-23 to enable CP10 and CP11 coprocessor
SCB->CPACR |= (0xF << 20);
#endif // (__VFP_FP__) && !(__SOFTFP__)
}
// ----------------------------------------------------------------------------
================================================
FILE: firmware/system/src/cortexm/_reset_hardware.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
#include "cmsis_device.h"
// ----------------------------------------------------------------------------
extern void
__attribute__((noreturn))
NVIC_SystemReset(void);
// ----------------------------------------------------------------------------
// Forward declarations
void
__reset_hardware(void);
// ----------------------------------------------------------------------------
// This is the default hardware reset routine; it can be
// redefined in the application for more complex applications.
//
// Called from _exit().
void
__attribute__((weak,noreturn))
__reset_hardware()
{
NVIC_SystemReset();
}
// ----------------------------------------------------------------------------
================================================
FILE: firmware/system/src/cortexm/exception_handlers.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
#include "cortexm/ExceptionHandlers.h"
// ----------------------------------------------------------------------------
extern void
__attribute__((noreturn))
_start(void);
// ----------------------------------------------------------------------------
// Default exception handlers. Override the ones here by defining your own
// handler routines in your application code.
// ----------------------------------------------------------------------------
#if defined(DEBUG)
// The DEBUG version is not naked, to allow breakpoints at Reset_Handler
void __attribute__ ((section(".after_vectors"),noreturn))
Reset_Handler (void)
{
_start ();
}
#else
// The Release version is optimised to a quick branch to _start.
void __attribute__ ((section(".after_vectors"),naked))
Reset_Handler(void)
{
asm volatile
(
" b _start \n"
:
:
:
);
}
#endif
void __attribute__ ((section(".after_vectors"),weak))
NMI_Handler(void)
{
while (1)
{
}
}
void __attribute__ ((section(".after_vectors"),weak))
HardFault_Handler(void)
{
while (1)
{
}
}
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
void __attribute__ ((section(".after_vectors"),weak))
MemManage_Handler(void)
{
while (1)
{
}
}
void __attribute__ ((section(".after_vectors"),weak))
BusFault_Handler(void)
{
while (1)
{
}
}
void __attribute__ ((section(".after_vectors"),weak))
UsageFault_Handler(void)
{
while (1)
{
}
}
#endif
void __attribute__ ((section(".after_vectors"),weak))
SVC_Handler(void)
{
while (1)
{
}
}
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
void __attribute__ ((section(".after_vectors"),weak))
DebugMon_Handler(void)
{
while (1)
{
}
}
#endif
void __attribute__ ((section(".after_vectors"),weak))
PendSV_Handler(void)
{
while (1)
{
}
}
void __attribute__ ((section(".after_vectors"),weak))
SysTick_Handler(void)
{
while (1)
{
}
}
================================================
FILE: firmware/system/src/diag/Trace.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
#if defined(TRACE)
#include
#include
#include "diag/Trace.h"
#include "string.h"
#ifndef OS_INTEGER_TRACE_PRINTF_TMP_ARRAY_SIZE
#define OS_INTEGER_TRACE_PRINTF_TMP_ARRAY_SIZE (128)
#endif
// ----------------------------------------------------------------------------
int
trace_printf(const char* format, ...)
{
int ret;
va_list ap;
va_start (ap, format);
// TODO: rewrite it to no longer use newlib, it is way too heavy
static char buf[OS_INTEGER_TRACE_PRINTF_TMP_ARRAY_SIZE];
// Print to the local buffer
ret = vsnprintf (buf, sizeof(buf), format, ap);
if (ret > 0)
{
// Transfer the buffer to the device
ret = trace_write (buf, (size_t)ret);
}
va_end (ap);
return ret;
}
int
trace_puts(const char *s)
{
trace_write(s, strlen(s));
return trace_write("\n", 1);
}
int
trace_putchar(int c)
{
trace_write((const char*)&c, 1);
return c;
}
void
trace_dump_args(int argc, char* argv[])
{
trace_printf("main(argc=%d, argv=[", argc);
for (int i = 0; i < argc; ++i)
{
if (i != 0)
{
trace_printf(", ");
}
trace_printf("\"%s\"", argv[i]);
}
trace_printf("]);\n");
}
// ----------------------------------------------------------------------------
#endif // TRACE
================================================
FILE: firmware/system/src/diag/trace_impl.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
#if defined(TRACE)
#include "cmsis_device.h"
#include "diag/Trace.h"
// ----------------------------------------------------------------------------
// One of these definitions must be passed via the compiler command line
// Note: small Cortex-M0/M0+ might implement a simplified debug interface.
//#define OS_USE_TRACE_ITM
//#define OS_USE_TRACE_SEMIHOSTING_DEBUG
//#define OS_USE_TRACE_SEMIHOSTING_STDOUT
#if !(defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__))
#if defined(OS_USE_TRACE_ITM)
#undef OS_USE_TRACE_ITM
#warning "ITM unavailable"
#endif // defined(OS_USE_TRACE_ITM)
#endif // !(defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__))
// ----------------------------------------------------------------------------
// Forward definitions.
#if defined(OS_USE_TRACE_ITM)
static ssize_t
_trace_write_itm (const char* buf, size_t nbyte);
#endif
#if defined(OS_USE_TRACE_SEMIHOSTING_STDOUT)
static ssize_t
_trace_write_semihosting_stdout(const char* buf, size_t nbyte);
#endif
#if defined(OS_USE_TRACE_SEMIHOSTING_DEBUG)
static ssize_t
_trace_write_semihosting_debug(const char* buf, size_t nbyte);
#endif
// ----------------------------------------------------------------------------
void
trace_initialize(void)
{
// No initialisations required for ITM / semihosting
}
// ----------------------------------------------------------------------------
// This function is called from _write() for fd==1 or fd==2 and from some
// of the trace_* functions.
ssize_t
trace_write (const char* buf __attribute__((unused)),
size_t nbyte __attribute__((unused)))
{
#if defined(OS_USE_TRACE_ITM)
return _trace_write_itm (buf, nbyte);
#elif defined(OS_USE_TRACE_SEMIHOSTING_STDOUT)
return _trace_write_semihosting_stdout(buf, nbyte);
#elif defined(OS_USE_TRACE_SEMIHOSTING_DEBUG)
return _trace_write_semihosting_debug(buf, nbyte);
#endif
return -1;
}
// ----------------------------------------------------------------------------
#if defined(OS_USE_TRACE_ITM)
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
// ITM is the ARM standard mechanism, running over SWD/SWO on Cortex-M3/M4
// devices, and is the recommended setting, if available.
//
// The JLink probe and the GDB server fully support SWD/SWO
// and the JLink Debugging plug-in enables it by default.
// The current OpenOCD does not include support to parse the SWO stream,
// so this configuration will not work on OpenOCD (will not crash, but
// nothing will be displayed in the output console).
#if !defined(OS_INTEGER_TRACE_ITM_STIMULUS_PORT)
#define OS_INTEGER_TRACE_ITM_STIMULUS_PORT (0)
#endif
static ssize_t
_trace_write_itm (const char* buf, size_t nbyte)
{
for (size_t i = 0; i < nbyte; i++)
{
// Check if ITM or the stimulus port are not enabled
if (((ITM->TCR & ITM_TCR_ITMENA_Msk) == 0)
|| ((ITM->TER & (1UL << OS_INTEGER_TRACE_ITM_STIMULUS_PORT)) == 0))
{
return (ssize_t)i; // return the number of sent characters (may be 0)
}
// Wait until STIMx is ready...
while (ITM->PORT[OS_INTEGER_TRACE_ITM_STIMULUS_PORT].u32 == 0)
;
// then send data, one byte at a time
ITM->PORT[OS_INTEGER_TRACE_ITM_STIMULUS_PORT].u8 = (uint8_t) (*buf++);
}
return (ssize_t)nbyte; // all characters successfully sent
}
#endif // defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
#endif // OS_USE_TRACE_ITM
// ----------------------------------------------------------------------------
#if defined(OS_USE_TRACE_SEMIHOSTING_DEBUG) || defined(OS_USE_TRACE_SEMIHOSTING_STDOUT)
#include "arm/semihosting.h"
// Semihosting is the other output channel that can be used for the trace
// messages. It comes in two flavours: STDOUT and DEBUG. The STDOUT channel
// is the equivalent of the stdout in POSIX and in most cases it is forwarded
// to the GDB server stdout stream. The debug channel is a separate
// channel. STDOUT is buffered, so nothing is displayed until a \n;
// DEBUG is not buffered, but can be slow.
//
// Choosing between semihosting stdout and debug depends on the capabilities
// of your GDB server, and also on specific needs. It is recommended to test
// DEBUG first, and if too slow, try STDOUT.
//
// The JLink GDB server fully support semihosting, and both configurations
// are available; to activate it, use "monitor semihosting enable" or check
// the corresponding button in the JLink Debugging plug-in.
// In OpenOCD, support for semihosting can be enabled using
// "monitor arm semihosting enable".
//
// Note: Applications built with semihosting output active cannot be
// executed without the debugger connected and active, since they use
// BKPT to communicate with the host. Attempts to run them standalone or
// without semihosting enabled will usually be terminated with hardware faults.
#endif // OS_USE_TRACE_SEMIHOSTING_DEBUG_*
// ----------------------------------------------------------------------------
#if defined(OS_USE_TRACE_SEMIHOSTING_STDOUT)
static ssize_t
_trace_write_semihosting_stdout (const char* buf, size_t nbyte)
{
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
// Check if the debugger is enabled. CoreDebug is available only on CM3/CM4.
// [Contributed by SourceForge user diabolo38]
if ((CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) == 0)
{
// If not, pretend we wrote all bytes
return (ssize_t) (nbyte);
}
#endif // defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
static int handle;
void* block[3];
int ret;
if (handle == 0)
{
// On the first call get the file handle from the host
block[0] = ":tt"; // special filename to be used for stdin/out/err
block[1] = (void*) 4; // mode "w"
// length of ":tt", except null terminator
block[2] = (void*) (sizeof(":tt") - 1);
ret = call_host (SEMIHOSTING_SYS_OPEN, (void*) block);
if (ret == -1)
return -1;
handle = ret;
}
block[0] = (void*) handle;
block[1] = (void*) buf;
block[2] = (void*) nbyte;
// send character array to host file/device
ret = call_host (SEMIHOSTING_SYS_WRITE, (void*) block);
// this call returns the number of bytes NOT written (0 if all ok)
// -1 is not a legal value, but SEGGER seems to return it
if (ret == -1)
return -1;
// The compliant way of returning errors
if (ret == (int) nbyte)
return -1;
// Return the number of bytes written
return (ssize_t) (nbyte) - (ssize_t) ret;
}
#endif // OS_USE_TRACE_SEMIHOSTING_STDOUT
// ----------------------------------------------------------------------------
#if defined(OS_USE_TRACE_SEMIHOSTING_DEBUG)
#define OS_INTEGER_TRACE_TMP_ARRAY_SIZE (16)
static ssize_t
_trace_write_semihosting_debug (const char* buf, size_t nbyte)
{
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
// Check if the debugger is enabled. CoreDebug is available only on CM3/CM4.
// [Contributed by SourceForge user diabolo38]
if ((CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk) == 0)
{
// If not, pretend we wrote all bytes
return (ssize_t) (nbyte);
}
#endif // defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
// Since the single character debug channel is quite slow, try to
// optimise and send a null terminated string, if possible.
if (buf[nbyte] == '\0')
{
// send string
call_host (SEMIHOSTING_SYS_WRITE0, (void*) buf);
}
else
{
// If not, use a local buffer to speed things up
char tmp[OS_INTEGER_TRACE_TMP_ARRAY_SIZE];
size_t togo = nbyte;
while (togo > 0)
{
unsigned int n = ((togo < sizeof(tmp)) ? togo : sizeof(tmp));
unsigned int i = 0;
for (; i < n; ++i, ++buf)
{
tmp[i] = *buf;
}
tmp[i] = '\0';
call_host (SEMIHOSTING_SYS_WRITE0, (void*) tmp);
togo -= n;
}
}
// All bytes written
return (ssize_t) nbyte;
}
#endif // OS_USE_TRACE_SEMIHOSTING_DEBUG
#endif // TRACE
// ----------------------------------------------------------------------------
================================================
FILE: firmware/system/src/newlib/README.txt
================================================
The following files extend or replace some of the the newlib functionality:
_startup.c: a customised startup sequence, written in C
_exit.c: a customised exit() implementation
_syscalls.c: local versions of the libnosys/librdimon code
_sbrk.c: a custom _sbrk() to match the actual linker scripts
assert.c: implementation for the asserion macros
_cxx.cpp: local versions of some C++ support, to avoid references to
large functions.
================================================
FILE: firmware/system/src/newlib/_cxx.cpp
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
// These functions are redefined locally, to avoid references to some
// heavy implementations in the standard C++ library.
// ----------------------------------------------------------------------------
#include
#include
#include "diag/Trace.h"
// ----------------------------------------------------------------------------
namespace __gnu_cxx
{
void
__attribute__((noreturn))
__verbose_terminate_handler();
void
__verbose_terminate_handler()
{
trace_puts(__func__);
abort();
}
}
// ----------------------------------------------------------------------------
extern "C"
{
void
__attribute__((noreturn))
__cxa_pure_virtual();
void
__cxa_pure_virtual()
{
trace_puts(__func__);
abort();
}
}
// ----------------------------------------------------------------------------
================================================
FILE: firmware/system/src/newlib/_exit.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
#include
#include "diag/Trace.h"
// ----------------------------------------------------------------------------
extern void
__attribute__((noreturn))
__reset_hardware(void);
// ----------------------------------------------------------------------------
// Forward declaration
void
_exit(int code);
// ----------------------------------------------------------------------------
// On Release, call the hardware reset procedure.
// On Debug we just enter an infinite loop, to be used as landmark when halting
// the debugger.
//
// It can be redefined in the application, if more functionality
// is required.
void
__attribute__((weak))
_exit(int code __attribute__((unused)))
{
#if !defined(DEBUG)
__reset_hardware();
#endif
// TODO: write on trace
while (1)
;
}
// ----------------------------------------------------------------------------
void
__attribute__((weak,noreturn))
abort(void)
{
trace_puts("abort(), exiting...");
_exit(1);
}
// ----------------------------------------------------------------------------
================================================
FILE: firmware/system/src/newlib/_sbrk.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
#include
#include
// ----------------------------------------------------------------------------
caddr_t
_sbrk(int incr);
// ----------------------------------------------------------------------------
// The definitions used here should be kept in sync with the
// stack definitions in the linker script.
caddr_t
_sbrk(int incr)
{
extern char _Heap_Begin; // Defined by the linker.
extern char _Heap_Limit; // Defined by the linker.
static char* current_heap_end;
char* current_block_address;
if (current_heap_end == 0)
current_heap_end = &_Heap_Begin;
current_block_address = current_heap_end;
// Need to align heap to word boundary, else will get
// hard faults on Cortex-M0. So we assume that heap starts on
// word boundary, hence make sure we always add a multiple of
// 4 to it.
incr = (incr + 3) & (~3); // align value to 4
if (current_heap_end + incr > &_Heap_Limit)
{
// Some of the libstdc++-v3 tests rely upon detecting
// out of memory errors, so do not abort here.
#if 0
extern void abort (void);
_write (1, "_sbrk: Heap and stack collision\n", 32);
abort ();
#else
// Heap has overflowed
errno = ENOMEM;
return (caddr_t) -1;
#endif
}
current_heap_end += incr;
return (caddr_t) current_block_address;
}
// ----------------------------------------------------------------------------
================================================
FILE: firmware/system/src/newlib/_startup.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// ----------------------------------------------------------------------------
// This module contains the startup code for a portable embedded
// C/C++ application, built with newlib.
//
// Control reaches here from the reset handler via jump or call.
//
// The actual steps performed by _start are:
// - clear the BSS area
// - copy the initialised data section
// - initialise the system
// - run the preinit/init array (for the C++ static constructors)
// - initialise the arc/argv
// - branch to main()
// - run the fini array (for the C++ static destructors)
// - call _exit(), directly or via exit()
//
// The normal configuration is standalone, with all support
// functions implemented locally.
//
// For this to be called, the project linker must be configured without
// the startup sequence (-nostartfiles).
// ----------------------------------------------------------------------------
#include
#include
// ----------------------------------------------------------------------------
#define OS_INCLUDE_STARTUP_GUARD_CHECKS (1)
// ----------------------------------------------------------------------------
// Begin address for the initialisation values of the .data section.
// defined in linker script
extern unsigned int _sidata;
// Begin address for the .data section; defined in linker script
extern unsigned int _sdata;
// End address for the .data section; defined in linker script
extern unsigned int _edata;
// Begin address for the .bss section; defined in linker script
extern unsigned int __bss_start__;
// End address for the .bss section; defined in linker script
extern unsigned int __bss_end__;
extern void
__initialize_args(int*, char***);
// main() is the entry point for newlib based applications.
// By default, there are no arguments, but this can be customised
// by redefining __initialize_args(), which is done when the
// semihosting configurations are used.
extern int
main(int argc, char* argv[]);
// The implementation for the exit routine; for embedded
// applications, a system reset will be performed.
extern void
__attribute__((noreturn))
_exit(int);
// ----------------------------------------------------------------------------
// Forward declarations
void
_start(void);
void
__initialize_data(unsigned int* from, unsigned int* section_begin,
unsigned int* section_end);
void
__initialize_bss(unsigned int* section_begin, unsigned int* section_end);
void
__run_init_array(void);
void
__run_fini_array(void);
void
__initialize_hardware(void);
// ----------------------------------------------------------------------------
inline void
__attribute__((always_inline))
__initialize_data(unsigned int* from, unsigned int* section_begin,
unsigned int* section_end)
{
// Iterate and copy word by word.
// It is assumed that the pointers are word aligned.
unsigned int *p = section_begin;
while (p < section_end)
*p++ = *from++;
}
inline void
__attribute__((always_inline))
__initialize_bss(unsigned int* section_begin, unsigned int* section_end)
{
// Iterate and clear word by word.
// It is assumed that the pointers are word aligned.
unsigned int *p = section_begin;
while (p < section_end)
*p++ = 0;
}
// These magic symbols are provided by the linker.
extern void
(*__preinit_array_start[])(void) __attribute__((weak));
extern void
(*__preinit_array_end[])(void) __attribute__((weak));
extern void
(*__init_array_start[])(void) __attribute__((weak));
extern void
(*__init_array_end[])(void) __attribute__((weak));
extern void
(*__fini_array_start[])(void) __attribute__((weak));
extern void
(*__fini_array_end[])(void) __attribute__((weak));
// Iterate over all the preinit/init routines (mainly static constructors).
inline void
__attribute__((always_inline))
__run_init_array(void)
{
int count;
int i;
count = __preinit_array_end - __preinit_array_start;
for (i = 0; i < count; i++)
__preinit_array_start[i]();
// If you need to run the code in the .init section, please use
// the startup files, since this requires the code in crti.o and crtn.o
// to add the function prologue/epilogue.
//_init(); // DO NOT ENABE THIS!
count = __init_array_end - __init_array_start;
for (i = 0; i < count; i++)
__init_array_start[i]();
}
// Run all the cleanup routines (mainly static destructors).
inline void
__attribute__((always_inline))
__run_fini_array(void)
{
int count;
int i;
count = __fini_array_end - __fini_array_start;
for (i = count; i > 0; i--)
__fini_array_start[i - 1]();
// If you need to run the code in the .fini section, please use
// the startup files, since this requires the code in crti.o and crtn.o
// to add the function prologue/epilogue.
//_fini(); // DO NOT ENABE THIS!
}
#if defined(DEBUG) && defined(OS_INCLUDE_STARTUP_GUARD_CHECKS)
// These definitions are used to check if the routines used to
// clear the BSS and to copy the initialised DATA perform correctly.
#define BSS_GUARD_BAD_VALUE (0xCADEBABA)
static uint32_t volatile __attribute__ ((section(".bss_begin")))
__bss_begin_guard;
static uint32_t volatile __attribute__ ((section(".bss_end")))
__bss_end_guard;
#define DATA_GUARD_BAD_VALUE (0xCADEBABA)
#define DATA_BEGIN_GUARD_VALUE (0x12345678)
#define DATA_END_GUARD_VALUE (0x98765432)
static uint32_t volatile __attribute__ ((section(".data_begin")))
__data_begin_guard = DATA_BEGIN_GUARD_VALUE;
static uint32_t volatile __attribute__ ((section(".data_end")))
__data_end_guard = DATA_END_GUARD_VALUE;
#endif // defined(DEBUG) && defined(OS_INCLUDE_STARTUP_GUARD_CHECKS)
// This is the place where Cortex-M core will go immediately after reset,
// via a call or jump from the Reset_Handler
void __attribute__ ((section(".after_vectors"),noreturn))
_start(void)
{
// Use Old Style Data and BSS section initialisation,
// that will initialise a single BSS sections.
#if defined(DEBUG) && defined(OS_INCLUDE_STARTUP_GUARD_CHECKS)
__bss_begin_guard = BSS_GUARD_BAD_VALUE;
__bss_end_guard = BSS_GUARD_BAD_VALUE;
#endif
// Zero fill the bss segment
__initialize_bss(&__bss_start__, &__bss_end__);
#if defined(DEBUG) && defined(OS_INCLUDE_STARTUP_GUARD_CHECKS)
if ((__bss_begin_guard != 0) || (__bss_end_guard != 0))
{
for (;;)
;
}
#endif
#if defined(DEBUG) && defined(OS_INCLUDE_STARTUP_GUARD_CHECKS)
__data_begin_guard = DATA_GUARD_BAD_VALUE;
__data_end_guard = DATA_GUARD_BAD_VALUE;
#endif
// Copy the data segment from Flash to RAM.
// When using startup files, this code is executed via the preinit array.
__initialize_data(&_sidata, &_sdata, &_edata);
#if defined(DEBUG) && defined(OS_INCLUDE_STARTUP_GUARD_CHECKS)
if ((__data_begin_guard != DATA_BEGIN_GUARD_VALUE) || (__data_end_guard != __data_end_guard))
{
for (;;)
;
}
#endif
__initialize_hardware();
// Get the args (useful in semihosting configurations).
int argc;
char** argv;
__initialize_args(&argc, &argv);
// Call the standard library initialisation (mandatory for C++ to
// execute the constructors for the static objects).
__run_init_array();
// Call the main entry point, and save the exit code.
int code = main(argc, argv);
// Run the C++ static destructors.
__run_fini_array();
_exit(code);
// Should never reach this, _exit() should have already
// performed a reset.
for (;;)
;
}
// ----------------------------------------------------------------------------
================================================
FILE: firmware/system/src/newlib/_syscalls.c
================================================
//
// This file is part of the µOS++ III distribution.
// Parts of this file are from the newlib sources, issued under GPL.
// Copyright (c) 2014 Liviu Ionescu
//
// ----------------------------------------------------------------------------
int errno;
// ----------------------------------------------------------------------------
#if !defined(OS_USE_SEMIHOSTING)
#include <_ansi.h>
#include <_syslist.h>
#include
//#include
#include
#include
#include
#include
#include
void
__initialize_args(int* p_argc, char*** p_argv);
// This is the standard default implementation for the routine to
// process args. It returns a single empty arg.
// For semihosting applications, this is redefined to get the real
// args from the debugger. You can also use it if you decide to keep
// some args in a non-volatile memory.
void __attribute__((weak))
__initialize_args(int* p_argc, char*** p_argv)
{
// By the time we reach this, the data and bss should have been initialised.
// The strings pointed to by the argv array shall be modifiable by the
// program, and retain their last-stored values between program startup
// and program termination. (static, no const)
static char name[] = "";
// The string pointed to by argv[0] represents the program name;
// argv[0][0] shall be the null character if the program name is not
// available from the host environment. argv[argc] shall be a null pointer.
// (static, no const)
static char* argv[2] =
{ name, NULL };
*p_argc = 1;
*p_argv = &argv[0];
return;
}
// These functions are defined here to avoid linker errors in freestanding
// applications. They might be called in some error cases from library
// code.
//
// If you detect other functions to be needed, just let us know
// and we'll add them.
int
raise(int sig __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int
kill(pid_t pid, int sig);
int
kill(pid_t pid __attribute__((unused)), int sig __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
#endif // !defined(OS_USE_SEMIHOSTING)
// ----------------------------------------------------------------------------
// If you need the empty definitions, remove the -ffreestanding option.
#if __STDC_HOSTED__ == 1
char* __env[1] =
{ 0 };
char** environ = __env;
#if !defined(OS_USE_SEMIHOSTING)
// Forward declarations
int
_chown(const char* path, uid_t owner, gid_t group);
int
_close(int fildes);
int
_execve(char* name, char** argv, char** env);
int
_fork(void);
int
_fstat(int fildes, struct stat* st);
int
_getpid(void);
int
_gettimeofday(struct timeval* ptimeval, void* ptimezone);
int
_isatty(int file);
int
_kill(int pid, int sig);
int
_link(char* existing, char* _new);
int
_lseek(int file, int ptr, int dir);
int
_open(char* file, int flags, int mode);
int
_read(int file, char* ptr, int len);
int
_readlink(const char* path, char* buf, size_t bufsize);
int
_stat(const char* file, struct stat* st);
int
_symlink(const char* path1, const char* path2);
clock_t
_times(struct tms* buf);
int
_unlink(char* name);
int
_wait(int* status);
int
_write(int file, char* ptr, int len);
// Definitions
int __attribute__((weak))
_chown(const char* path __attribute__((unused)),
uid_t owner __attribute__((unused)), gid_t group __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_close(int fildes __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_execve(char* name __attribute__((unused)), char** argv __attribute__((unused)),
char** env __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_fork(void)
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_fstat(int fildes __attribute__((unused)),
struct stat* st __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_getpid(void)
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_gettimeofday(struct timeval* ptimeval __attribute__((unused)),
void* ptimezone __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_isatty(int file __attribute__((unused)))
{
errno = ENOSYS;
return 0;
}
int __attribute__((weak))
_kill(int pid __attribute__((unused)), int sig __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_link(char* existing __attribute__((unused)),
char* _new __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_lseek(int file __attribute__((unused)), int ptr __attribute__((unused)),
int dir __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_open(char* file __attribute__((unused)), int flags __attribute__((unused)),
int mode __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_read(int file __attribute__((unused)), char* ptr __attribute__((unused)),
int len __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_readlink(const char* path __attribute__((unused)),
char* buf __attribute__((unused)), size_t bufsize __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_stat(const char* file __attribute__((unused)),
struct stat* st __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_symlink(const char* path1 __attribute__((unused)),
const char* path2 __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
clock_t __attribute__((weak))
_times(struct tms* buf __attribute__((unused)))
{
errno = ENOSYS;
return ((clock_t) -1);
}
int __attribute__((weak))
_unlink(char* name __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_wait(int* status __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
int __attribute__((weak))
_write(int file __attribute__((unused)), char* ptr __attribute__((unused)),
int len __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
// ----------------------------------------------------------------------------
#else // defined(OS_USE_SEMIHOSTING)
// ----------------------------------------------------------------------------
/* Support files for GNU libc. Files in the system namespace go here.
Files in the C namespace (ie those that do not start with an
underscore) go in .c. */
#include <_ansi.h>
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "arm/semihosting.h"
int
_kill (int pid, int sig);
void
__attribute__((noreturn))
_exit (int status);
// Forward declarations.
int
_system (const char*);
int
_rename (const char*, const char*);
int
_isatty (int);
clock_t
_times (struct tms*);
int
_gettimeofday (struct timeval *, void*);
int
_unlink (const char*);
int
_link (void);
int
_stat (const char*, struct stat*);
int
_fstat (int, struct stat*);
int
_swistat (int fd, struct stat* st);
int
_getpid (int);
int
_close (int);
clock_t
_clock (void);
int
_swiclose (int);
int
_open (const char*, int, ...);
int
_swiopen (const char*, int);
int
_write (int, char*, int);
int
_swiwrite (int, char*, int);
int
_lseek (int, int, int);
int
_swilseek (int, int, int);
int
_read (int, char*, int);
int
_swiread (int, char*, int);
void
initialise_monitor_handles (void);
void
__initialize_args (int* p_argc, char*** p_argv);
static int
checkerror (int);
static int
error (int);
static int
get_errno (void);
// ----------------------------------------------------------------------------
#define ARGS_BUF_ARRAY_SIZE 80
#define ARGV_BUF_ARRAY_SIZE 10
typedef struct
{
char* pCommandLine;
int size;
}CommandLineBlock;
void
__initialize_args (int* p_argc, char*** p_argv)
{
// Array of chars to receive the command line from the host
static char args_buf[ARGS_BUF_ARRAY_SIZE];
// Array of pointers to store the final argv pointers (pointing
// in the above array).
static char* argv_buf[ARGV_BUF_ARRAY_SIZE];
int argc = 0;
int isInArgument = 0;
CommandLineBlock cmdBlock;
cmdBlock.pCommandLine = args_buf;
cmdBlock.size = sizeof(args_buf) - 1;
int ret = call_host (SEMIHOSTING_SYS_GET_CMDLINE, &cmdBlock);
if (ret == 0)
{
// In case the host send more than we can chew, limit the
// string to our buffer.
args_buf[ARGS_BUF_ARRAY_SIZE - 1] = '\0';
// The command line is a null terminated string
char* p = cmdBlock.pCommandLine;
int delim = '\0';
int ch;
while ((ch = *p) != '\0')
{
if (isInArgument == 0)
{
if (!isblank(ch))
{
if (argc
>= (int) ((sizeof(argv_buf) / sizeof(argv_buf[0])) - 1))
break;
if (ch == '"' || ch == '\'')
{
// Remember the delimiter to search for the
// corresponding terminator
delim = ch;
++p;// skip the delimiter
ch = *p;
}
// Remember the arg beginning address
argv_buf[argc++] = p;
isInArgument = 1;
}
}
else
{
if ((ch == delim) || isblank(ch))
{
delim = '\0';
*p = '\0';
isInArgument = 0;
}
}
++p;
}
}
if (argc == 0)
{
// No args found in string, return a single empty name.
args_buf[0] = '\0';
argv_buf[0] = &args_buf[0];
++argc;
}
// Must end the array with a null pointer.
argv_buf[argc] = NULL;
*p_argc = argc;
*p_argv = &argv_buf[0];
// temporary here
initialise_monitor_handles ();
return;
}
// ----------------------------------------------------------------------------
void
_exit (int status)
{
/* There is only one SWI for both _exit and _kill. For _exit, call
the SWI with the second argument set to -1, an invalid value for
signum, so that the SWI handler can distinguish the two calls.
Note: The RDI implementation of _kill throws away both its
arguments. */
report_exception (
status == 0 ? ADP_Stopped_ApplicationExit : ADP_Stopped_RunTimeError);
}
// ----------------------------------------------------------------------------
int __attribute__((weak))
_kill(int pid __attribute__((unused)), int sig __attribute__((unused)))
{
errno = ENOSYS;
return -1;
}
// ----------------------------------------------------------------------------
/* Struct used to keep track of the file position, just so we
can implement fseek(fh,x,SEEK_CUR). */
struct fdent
{
int handle;
int pos;
};
#define MAX_OPEN_FILES 20
/* User file descriptors (fd) are integer indexes into
the openfiles[] array. Error checking is done by using
findslot().
This openfiles array is manipulated directly by only
these 5 functions:
findslot() - Translate entry.
newslot() - Find empty entry.
initilise_monitor_handles() - Initialize entries.
_swiopen() - Initialize entry.
_close() - Handle stdout == stderr case.
Every other function must use findslot(). */
static struct fdent openfiles[MAX_OPEN_FILES];
static struct fdent*
findslot (int);
static int
newslot (void);
/* Register name faking - works in collusion with the linker. */
register char* stack_ptr asm ("sp");
/* following is copied from libc/stdio/local.h to check std streams */
extern void _EXFUN(__sinit,(struct _reent*));
#define CHECK_INIT(ptr) \
do \
{ \
if ((ptr) && !(ptr)->__sdidinit) \
__sinit (ptr); \
} \
while (0)
static int monitor_stdin;
static int monitor_stdout;
static int monitor_stderr;
/* Return a pointer to the structure associated with
the user file descriptor fd. */
static struct fdent*
findslot (int fd)
{
CHECK_INIT(_REENT);
/* User file descriptor is out of range. */
if ((unsigned int) fd >= MAX_OPEN_FILES)
return NULL;
/* User file descriptor is open? */
if (openfiles[fd].handle == -1)
return NULL;
/* Valid. */
return &openfiles[fd];
}
/* Return the next lowest numbered free file
structure, or -1 if we can't find one. */
static int
newslot (void)
{
int i;
for (i = 0; i < MAX_OPEN_FILES; i++)
if (openfiles[i].handle == -1)
break;
if (i == MAX_OPEN_FILES)
return -1;
return i;
}
void
initialise_monitor_handles (void)
{
int i;
/* Open the standard file descriptors by opening the special
* teletype device, ":tt", read-only to obtain a descriptor for
* standard input and write-only to obtain a descriptor for standard
* output. Finally, open ":tt" in append mode to obtain a descriptor
* for standard error. Since this is a write mode, most kernels will
* probably return the same value as for standard output, but the
* kernel can differentiate the two using the mode flag and return a
* different descriptor for standard error.
*/
int volatile block[3];
block[0] = (int) ":tt";
block[2] = 3; /* length of filename */
block[1] = 0; /* mode "r" */
monitor_stdin = call_host (SEMIHOSTING_SYS_OPEN, (void*) block);
block[0] = (int) ":tt";
block[2] = 3; /* length of filename */
block[1] = 4; /* mode "w" */
monitor_stdout = call_host (SEMIHOSTING_SYS_OPEN, (void*) block);
block[0] = (int) ":tt";
block[2] = 3; /* length of filename */
block[1] = 8; /* mode "a" */
monitor_stderr = call_host (SEMIHOSTING_SYS_OPEN, (void*) block);
/* If we failed to open stderr, redirect to stdout. */
if (monitor_stderr == -1)
monitor_stderr = monitor_stdout;
for (i = 0; i < MAX_OPEN_FILES; i++)
openfiles[i].handle = -1;
openfiles[0].handle = monitor_stdin;
openfiles[0].pos = 0;
openfiles[1].handle = monitor_stdout;
openfiles[1].pos = 0;
openfiles[2].handle = monitor_stderr;
openfiles[2].pos = 0;
}
static int
get_errno (void)
{
return call_host (SEMIHOSTING_SYS_ERRNO, NULL);
}
/* Set errno and return result. */
static int
error (int result)
{
errno = get_errno ();
return result;
}
/* Check the return and set errno appropriately. */
static int
checkerror (int result)
{
if (result == -1)
return error (-1);
return result;
}
/* fh, is a valid internal file handle.
ptr, is a null terminated string.
len, is the length in bytes to read.
Returns the number of bytes *not* written. */
int
_swiread (int fh, char* ptr, int len)
{
int block[3];
block[0] = fh;
block[1] = (int) ptr;
block[2] = len;
return checkerror (call_host (SEMIHOSTING_SYS_READ, block));
}
/* fd, is a valid user file handle.
Translates the return of _swiread into
bytes read. */
int
_read (int fd, char* ptr, int len)
{
int res;
struct fdent *pfd;
pfd = findslot (fd);
if (pfd == NULL)
{
errno = EBADF;
return -1;
}
res = _swiread (pfd->handle, ptr, len);
if (res == -1)
return res;
pfd->pos += len - res;
/* res == len is not an error,
at least if we want feof() to work. */
return len - res;
}
/* fd, is a user file descriptor. */
int
_swilseek (int fd, int ptr, int dir)
{
int res;
struct fdent *pfd;
/* Valid file descriptor? */
pfd = findslot (fd);
if (pfd == NULL)
{
errno = EBADF;
return -1;
}
/* Valid whence? */
if ((dir != SEEK_CUR) && (dir != SEEK_SET) && (dir != SEEK_END))
{
errno = EINVAL;
return -1;
}
/* Convert SEEK_CUR to SEEK_SET */
if (dir == SEEK_CUR)
{
ptr = pfd->pos + ptr;
/* The resulting file offset would be negative. */
if (ptr < 0)
{
errno = EINVAL;
if ((pfd->pos > 0) && (ptr > 0))
errno = EOVERFLOW;
return -1;
}
dir = SEEK_SET;
}
int block[2];
if (dir == SEEK_END)
{
block[0] = pfd->handle;
res = checkerror (call_host (SEMIHOSTING_SYS_FLEN, block));
if (res == -1)
return -1;
ptr += res;
}
/* This code only does absolute seeks. */
block[0] = pfd->handle;
block[1] = ptr;
res = checkerror (call_host (SEMIHOSTING_SYS_SEEK, block));
/* At this point ptr is the current file position. */
if (res >= 0)
{
pfd->pos = ptr;
return ptr;
}
else
return -1;
}
int
_lseek (int fd, int ptr, int dir)
{
return _swilseek (fd, ptr, dir);
}
/* fh, is a valid internal file handle.
Returns the number of bytes *not* written. */
int
_swiwrite (int fh, char* ptr, int len)
{
int block[3];
block[0] = fh;
block[1] = (int) ptr;
block[2] = len;
return checkerror (call_host (SEMIHOSTING_SYS_WRITE, block));
}
/* fd, is a user file descriptor. */
int
_write (int fd, char* ptr, int len)
{
int res;
struct fdent *pfd;
pfd = findslot (fd);
if (pfd == NULL)
{
errno = EBADF;
return -1;
}
res = _swiwrite (pfd->handle, ptr, len);
/* Clearly an error. */
if (res < 0)
return -1;
pfd->pos += len - res;
/* We wrote 0 bytes?
Retrieve errno just in case. */
if ((len - res) == 0)
return error (0);
return (len - res);
}
int
_swiopen (const char* path, int flags)
{
int aflags = 0, fh;
uint32_t block[3];
int fd = newslot ();
if (fd == -1)
{
errno = EMFILE;
return -1;
}
/* It is an error to open a file that already exists. */
if ((flags & O_CREAT) && (flags & O_EXCL))
{
struct stat st;
int res;
res = _stat (path, &st);
if (res != -1)
{
errno = EEXIST;
return -1;
}
}
/* The flags are Unix-style, so we need to convert them. */
#ifdef O_BINARY
if (flags & O_BINARY)
aflags |= 1;
#endif
/* In O_RDONLY we expect aflags == 0. */
if (flags & O_RDWR)
aflags |= 2;
if ((flags & O_CREAT) || (flags & O_TRUNC) || (flags & O_WRONLY))
aflags |= 4;
if (flags & O_APPEND)
{
/* Can't ask for w AND a; means just 'a'. */
aflags &= ~4;
aflags |= 8;
}
block[0] = (uint32_t) path;
block[2] = strlen (path);
block[1] = (uint32_t) aflags;
fh = call_host (SEMIHOSTING_SYS_OPEN, block);
/* Return a user file descriptor or an error. */
if (fh >= 0)
{
openfiles[fd].handle = fh;
openfiles[fd].pos = 0;
return fd;
}
else
return error (fh);
}
int
_open (const char* path, int flags, ...)
{
return _swiopen (path, flags);
}
/* fh, is a valid internal file handle. */
int
_swiclose (int fh)
{
return checkerror (call_host (SEMIHOSTING_SYS_CLOSE, &fh));
}
/* fd, is a user file descriptor. */
int
_close (int fd)
{
int res;
struct fdent *pfd;
pfd = findslot (fd);
if (pfd == NULL)
{
errno = EBADF;
return -1;
}
/* Handle stderr == stdout. */
if ((fd == 1 || fd == 2) && (openfiles[1].handle == openfiles[2].handle))
{
pfd->handle = -1;
return 0;
}
/* Attempt to close the handle. */
res = _swiclose (pfd->handle);
/* Reclaim handle? */
if (res == 0)
pfd->handle = -1;
return res;
}
int __attribute__((weak))
_getpid (int n __attribute__ ((unused)))
{
return 1;
}
int
_swistat (int fd, struct stat* st)
{
struct fdent *pfd;
int res;
pfd = findslot (fd);
if (pfd == NULL)
{
errno = EBADF;
return -1;
}
/* Always assume a character device,
with 1024 byte blocks. */
st->st_mode |= S_IFCHR;
st->st_blksize = 1024;
res = checkerror (call_host (SEMIHOSTING_SYS_FLEN, &pfd->handle));
if (res == -1)
return -1;
/* Return the file size. */
st->st_size = res;
return 0;
}
int __attribute__((weak))
_fstat (int fd, struct stat* st)
{
memset (st, 0, sizeof(*st));
return _swistat (fd, st);
}
int __attribute__((weak))
_stat (const char*fname, struct stat *st)
{
int fd, res;
memset (st, 0, sizeof(*st));
/* The best we can do is try to open the file readonly.
If it exists, then we can guess a few things about it. */
if ((fd = _open (fname, O_RDONLY)) == -1)
return -1;
st->st_mode |= S_IFREG | S_IREAD;
res = _swistat (fd, st);
/* Not interested in the error. */
_close (fd);
return res;
}
int __attribute__((weak))
_link (void)
{
errno = ENOSYS;
return -1;
}
int
_unlink (const char* path)
{
int res;
uint32_t block[2];
block[0] = (uint32_t) path;
block[1] = strlen (path);
res = call_host (SEMIHOSTING_SYS_REMOVE, block);
if (res == -1)
return error (res);
return 0;
}
int
_gettimeofday (struct timeval* tp, void* tzvp)
{
struct timezone* tzp = tzvp;
if (tp)
{
/* Ask the host for the seconds since the Unix epoch. */
tp->tv_sec = call_host (SEMIHOSTING_SYS_TIME, NULL);
tp->tv_usec = 0;
}
/* Return fixed data for the timezone. */
if (tzp)
{
tzp->tz_minuteswest = 0;
tzp->tz_dsttime = 0;
}
return 0;
}
/* Return a clock that ticks at 100Hz. */
clock_t
_clock (void)
{
clock_t timeval;
timeval = (clock_t)call_host (SEMIHOSTING_SYS_CLOCK, NULL);
return timeval;
}
/* Return a clock that ticks at 100Hz. */
clock_t
_times (struct tms* tp)
{
clock_t timeval = _clock ();
if (tp)
{
tp->tms_utime = timeval; /* user time */
tp->tms_stime = 0; /* system time */
tp->tms_cutime = 0; /* user time, children */
tp->tms_cstime = 0; /* system time, children */
}
return timeval;
}
;
int
_isatty (int fd)
{
struct fdent *pfd;
int tty;
pfd = findslot (fd);
if (pfd == NULL)
{
errno = EBADF;
return 0;
}
tty = call_host (SEMIHOSTING_SYS_ISTTY, &pfd->handle);
if (tty == 1)
return 1;
errno = get_errno ();
return 0;
}
int
_system (const char* s)
{
uint32_t block[2];
int e;
/* Hmmm. The ARM debug interface specification doesn't say whether
SYS_SYSTEM does the right thing with a null argument, or assign any
meaning to its return value. Try to do something reasonable.... */
if (!s)
return 1; /* maybe there is a shell available? we can hope. :-P */
block[0] = (uint32_t) s;
block[1] = strlen (s);
e = checkerror (call_host (SEMIHOSTING_SYS_SYSTEM, block));
if ((e >= 0) && (e < 256))
{
/* We have to convert e, an exit status to the encoded status of
the command. To avoid hard coding the exit status, we simply
loop until we find the right position. */
int exit_code;
for (exit_code = e; e && WEXITSTATUS (e) != exit_code; e <<= 1)
continue;
}
return e;
}
int
_rename (const char* oldpath, const char* newpath)
{
uint32_t block[4];
block[0] = (uint32_t) oldpath;
block[1] = strlen (oldpath);
block[2] = (uint32_t) newpath;
block[3] = strlen (newpath);
return checkerror (call_host (SEMIHOSTING_SYS_RENAME, block)) ? -1 : 0;
}
// ----------------------------------------------------------------------------
// Required by Google Tests
int
mkdir(const char *path __attribute__((unused)), mode_t mode __attribute__((unused)))
{
#if 0
// always return true
return 0;
#else
errno = ENOSYS;
return -1;
#endif
}
char *
getcwd(char *buf, size_t size)
{
// no cwd available via semihosting, so we use the temporary folder
strncpy(buf, "/tmp", size);
return buf;
}
#endif // defined OS_USE_SEMIHOSTING
#endif // __STDC_HOSTED__ == 1
================================================
FILE: firmware/system/src/newlib/_write.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
// Do not include on semihosting and when freestanding
#if !defined(OS_USE_SEMIHOSTING) && !(__STDC_HOSTED__ == 0)
// ----------------------------------------------------------------------------
#include
#include "diag/Trace.h"
// ----------------------------------------------------------------------------
// When using retargetted configurations, the standard write() system call,
// after a long way inside newlib, finally calls this implementation function.
// Based on the file descriptor, it can send arrays of characters to
// different physical devices.
// Currently only the output and error file descriptors are tested,
// and the characters are forwarded to the trace device, mainly
// for demonstration purposes.
ssize_t
_write (int fd, const char* buf, size_t nbyte);
ssize_t
_write (int fd __attribute__((unused)), const char* buf __attribute__((unused)),
size_t nbyte __attribute__((unused)))
{
#if defined(TRACE)
// STDOUT and STDERR are routed to the trace device
if (fd == 1 || fd == 2)
{
return trace_write (buf, nbyte);
}
#endif // TRACE
errno = ENOSYS;
return -1;
}
// ----------------------------------------------------------------------------
#endif // !defined(OS_USE_SEMIHOSTING) && !(__STDC_HOSTED__ == 0)
================================================
FILE: firmware/system/src/newlib/assert.c
================================================
//
// This file is part of the µOS++ III distribution.
// Copyright (c) 2014 Liviu Ionescu.
//
#include
#include
#include
#include "diag/Trace.h"
// ----------------------------------------------------------------------------
void
__attribute__((noreturn))
__assert_func (const char *file, int line, const char *func,
const char *failedexpr)
{
trace_printf ("assertion \"%s\" failed: file \"%s\", line %d%s%s\n",
failedexpr, file, line, func ? ", function: " : "",
func ? func : "");
abort ();
/* NOTREACHED */
}
// ----------------------------------------------------------------------------
// This is STM32 specific, but can be used on other platforms too.
// If you need it, add the following to your application header:
//#ifdef USE_FULL_ASSERT
//#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
//void assert_failed(uint8_t* file, uint32_t line);
//#else
//#define assert_param(expr) ((void)0)
//#endif // USE_FULL_ASSERT
#if defined(USE_FULL_ASSERT)
void
assert_failed (uint8_t* file, uint32_t line);
// Called from the assert_param() macro, usually defined in the stm32f*_conf.h
void
__attribute__((noreturn))
assert_failed (uint8_t* file, uint32_t line)
{
trace_printf ("assert_param() failed: file \"%s\", line %d\n", file, line);
abort ();
/* NOTREACHED */
}
#endif // defined(USE_FULL_ASSERT)
// ----------------------------------------------------------------------------
================================================
FILE: firmware/system/src/stm32f1-stdperiph/README_STDPERIPH.txt
================================================
These files are from stsw-stm32054.zip, the folder:
STM32F10x_StdPeriph_Lib_V3.5.0/Libraries/STM32F10x_StdPeriph_Driver/src
================================================
FILE: firmware/system/src/stm32f1-stdperiph/misc.c
================================================
/**
******************************************************************************
* @file misc.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the miscellaneous firmware functions (add-on
* to CMSIS functions).
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "misc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup MISC
* @brief MISC driver modules
* @{
*/
/** @defgroup MISC_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup MISC_Private_Defines
* @{
*/
#define AIRCR_VECTKEY_MASK ((uint32_t)0x05FA0000)
/**
* @}
*/
/** @defgroup MISC_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup MISC_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup MISC_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup MISC_Private_Functions
* @{
*/
/**
* @brief Configures the priority grouping: pre-emption priority and subpriority.
* @param NVIC_PriorityGroup: specifies the priority grouping bits length.
* This parameter can be one of the following values:
* @arg NVIC_PriorityGroup_0: 0 bits for pre-emption priority
* 4 bits for subpriority
* @arg NVIC_PriorityGroup_1: 1 bits for pre-emption priority
* 3 bits for subpriority
* @arg NVIC_PriorityGroup_2: 2 bits for pre-emption priority
* 2 bits for subpriority
* @arg NVIC_PriorityGroup_3: 3 bits for pre-emption priority
* 1 bits for subpriority
* @arg NVIC_PriorityGroup_4: 4 bits for pre-emption priority
* 0 bits for subpriority
* @retval None
*/
void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup)
{
/* Check the parameters */
assert_param(IS_NVIC_PRIORITY_GROUP(NVIC_PriorityGroup));
/* Set the PRIGROUP[10:8] bits according to NVIC_PriorityGroup value */
SCB->AIRCR = AIRCR_VECTKEY_MASK | NVIC_PriorityGroup;
}
/**
* @brief Initializes the NVIC peripheral according to the specified
* parameters in the NVIC_InitStruct.
* @param NVIC_InitStruct: pointer to a NVIC_InitTypeDef structure that contains
* the configuration information for the specified NVIC peripheral.
* @retval None
*/
void NVIC_Init(NVIC_InitTypeDef* NVIC_InitStruct)
{
uint32_t tmppriority = 0x00, tmppre = 0x00, tmpsub = 0x0F;
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NVIC_InitStruct->NVIC_IRQChannelCmd));
assert_param(IS_NVIC_PREEMPTION_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority));
assert_param(IS_NVIC_SUB_PRIORITY(NVIC_InitStruct->NVIC_IRQChannelSubPriority));
if (NVIC_InitStruct->NVIC_IRQChannelCmd != DISABLE)
{
/* Compute the Corresponding IRQ Priority --------------------------------*/
tmppriority = (0x700 - ((SCB->AIRCR) & (uint32_t)0x700))>> 0x08;
tmppre = (0x4 - tmppriority);
tmpsub = tmpsub >> tmppriority;
tmppriority = (uint32_t)NVIC_InitStruct->NVIC_IRQChannelPreemptionPriority << tmppre;
tmppriority |= NVIC_InitStruct->NVIC_IRQChannelSubPriority & tmpsub;
tmppriority = tmppriority << 0x04;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
NVIC->IP[NVIC_InitStruct->NVIC_IRQChannel] = tmppriority;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/* Enable the Selected IRQ Channels --------------------------------------*/
NVIC->ISER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
else
{
/* Disable the Selected IRQ Channels -------------------------------------*/
NVIC->ICER[NVIC_InitStruct->NVIC_IRQChannel >> 0x05] =
(uint32_t)0x01 << (NVIC_InitStruct->NVIC_IRQChannel & (uint8_t)0x1F);
}
}
/**
* @brief Sets the vector table location and Offset.
* @param NVIC_VectTab: specifies if the vector table is in RAM or FLASH memory.
* This parameter can be one of the following values:
* @arg NVIC_VectTab_RAM
* @arg NVIC_VectTab_FLASH
* @param Offset: Vector Table base offset field. This value must be a multiple
* of 0x200.
* @retval None
*/
void NVIC_SetVectorTable(uint32_t NVIC_VectTab, uint32_t Offset)
{
/* Check the parameters */
assert_param(IS_NVIC_VECTTAB(NVIC_VectTab));
assert_param(IS_NVIC_OFFSET(Offset));
SCB->VTOR = NVIC_VectTab | (Offset & (uint32_t)0x1FFFFF80);
}
/**
* @brief Selects the condition for the system to enter low power mode.
* @param LowPowerMode: Specifies the new mode for the system to enter low power mode.
* This parameter can be one of the following values:
* @arg NVIC_LP_SEVONPEND
* @arg NVIC_LP_SLEEPDEEP
* @arg NVIC_LP_SLEEPONEXIT
* @param NewState: new state of LP condition. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void NVIC_SystemLPConfig(uint8_t LowPowerMode, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_NVIC_LP(LowPowerMode));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
SCB->SCR |= LowPowerMode;
}
else
{
SCB->SCR &= (uint32_t)(~(uint32_t)LowPowerMode);
}
}
/**
* @brief Configures the SysTick clock source.
* @param SysTick_CLKSource: specifies the SysTick clock source.
* This parameter can be one of the following values:
* @arg SysTick_CLKSource_HCLK_Div8: AHB clock divided by 8 selected as SysTick clock source.
* @arg SysTick_CLKSource_HCLK: AHB clock selected as SysTick clock source.
* @retval None
*/
void SysTick_CLKSourceConfig(uint32_t SysTick_CLKSource)
{
/* Check the parameters */
assert_param(IS_SYSTICK_CLK_SOURCE(SysTick_CLKSource));
if (SysTick_CLKSource == SysTick_CLKSource_HCLK)
{
SysTick->CTRL |= SysTick_CLKSource_HCLK;
}
else
{
SysTick->CTRL &= SysTick_CLKSource_HCLK_Div8;
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_adc.c
================================================
/**
******************************************************************************
* @file stm32f10x_adc.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the ADC firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_adc.h"
#include "stm32f10x_rcc.h"
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup ADC
* @brief ADC driver modules
* @{
*/
/** @defgroup ADC_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup ADC_Private_Defines
* @{
*/
/* ADC DISCNUM mask */
#define CR1_DISCNUM_Reset ((uint32_t)0xFFFF1FFF)
/* ADC DISCEN mask */
#define CR1_DISCEN_Set ((uint32_t)0x00000800)
#define CR1_DISCEN_Reset ((uint32_t)0xFFFFF7FF)
/* ADC JAUTO mask */
#define CR1_JAUTO_Set ((uint32_t)0x00000400)
#define CR1_JAUTO_Reset ((uint32_t)0xFFFFFBFF)
/* ADC JDISCEN mask */
#define CR1_JDISCEN_Set ((uint32_t)0x00001000)
#define CR1_JDISCEN_Reset ((uint32_t)0xFFFFEFFF)
/* ADC AWDCH mask */
#define CR1_AWDCH_Reset ((uint32_t)0xFFFFFFE0)
/* ADC Analog watchdog enable mode mask */
#define CR1_AWDMode_Reset ((uint32_t)0xFF3FFDFF)
/* CR1 register Mask */
#define CR1_CLEAR_Mask ((uint32_t)0xFFF0FEFF)
/* ADC ADON mask */
#define CR2_ADON_Set ((uint32_t)0x00000001)
#define CR2_ADON_Reset ((uint32_t)0xFFFFFFFE)
/* ADC DMA mask */
#define CR2_DMA_Set ((uint32_t)0x00000100)
#define CR2_DMA_Reset ((uint32_t)0xFFFFFEFF)
/* ADC RSTCAL mask */
#define CR2_RSTCAL_Set ((uint32_t)0x00000008)
/* ADC CAL mask */
#define CR2_CAL_Set ((uint32_t)0x00000004)
/* ADC SWSTART mask */
#define CR2_SWSTART_Set ((uint32_t)0x00400000)
/* ADC EXTTRIG mask */
#define CR2_EXTTRIG_Set ((uint32_t)0x00100000)
#define CR2_EXTTRIG_Reset ((uint32_t)0xFFEFFFFF)
/* ADC Software start mask */
#define CR2_EXTTRIG_SWSTART_Set ((uint32_t)0x00500000)
#define CR2_EXTTRIG_SWSTART_Reset ((uint32_t)0xFFAFFFFF)
/* ADC JEXTSEL mask */
#define CR2_JEXTSEL_Reset ((uint32_t)0xFFFF8FFF)
/* ADC JEXTTRIG mask */
#define CR2_JEXTTRIG_Set ((uint32_t)0x00008000)
#define CR2_JEXTTRIG_Reset ((uint32_t)0xFFFF7FFF)
/* ADC JSWSTART mask */
#define CR2_JSWSTART_Set ((uint32_t)0x00200000)
/* ADC injected software start mask */
#define CR2_JEXTTRIG_JSWSTART_Set ((uint32_t)0x00208000)
#define CR2_JEXTTRIG_JSWSTART_Reset ((uint32_t)0xFFDF7FFF)
/* ADC TSPD mask */
#define CR2_TSVREFE_Set ((uint32_t)0x00800000)
#define CR2_TSVREFE_Reset ((uint32_t)0xFF7FFFFF)
/* CR2 register Mask */
#define CR2_CLEAR_Mask ((uint32_t)0xFFF1F7FD)
/* ADC SQx mask */
#define SQR3_SQ_Set ((uint32_t)0x0000001F)
#define SQR2_SQ_Set ((uint32_t)0x0000001F)
#define SQR1_SQ_Set ((uint32_t)0x0000001F)
/* SQR1 register Mask */
#define SQR1_CLEAR_Mask ((uint32_t)0xFF0FFFFF)
/* ADC JSQx mask */
#define JSQR_JSQ_Set ((uint32_t)0x0000001F)
/* ADC JL mask */
#define JSQR_JL_Set ((uint32_t)0x00300000)
#define JSQR_JL_Reset ((uint32_t)0xFFCFFFFF)
/* ADC SMPx mask */
#define SMPR1_SMP_Set ((uint32_t)0x00000007)
#define SMPR2_SMP_Set ((uint32_t)0x00000007)
/* ADC JDRx registers offset */
#define JDR_Offset ((uint8_t)0x28)
/* ADC1 DR register base address */
#define DR_ADDRESS ((uint32_t)0x4001244C)
/**
* @}
*/
/** @defgroup ADC_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup ADC_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup ADC_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup ADC_Private_Functions
* @{
*/
/**
* @brief Deinitializes the ADCx peripheral registers to their default reset values.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @retval None
*/
void ADC_DeInit(ADC_TypeDef* ADCx)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
if (ADCx == ADC1)
{
/* Enable ADC1 reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE);
/* Release ADC1 from reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE);
}
else if (ADCx == ADC2)
{
/* Enable ADC2 reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, ENABLE);
/* Release ADC2 from reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC2, DISABLE);
}
else
{
if (ADCx == ADC3)
{
/* Enable ADC3 reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, ENABLE);
/* Release ADC3 from reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC3, DISABLE);
}
}
}
/**
* @brief Initializes the ADCx peripheral according to the specified parameters
* in the ADC_InitStruct.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_InitStruct: pointer to an ADC_InitTypeDef structure that contains
* the configuration information for the specified ADC peripheral.
* @retval None
*/
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct)
{
uint32_t tmpreg1 = 0;
uint8_t tmpreg2 = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_MODE(ADC_InitStruct->ADC_Mode));
assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ScanConvMode));
assert_param(IS_FUNCTIONAL_STATE(ADC_InitStruct->ADC_ContinuousConvMode));
assert_param(IS_ADC_EXT_TRIG(ADC_InitStruct->ADC_ExternalTrigConv));
assert_param(IS_ADC_DATA_ALIGN(ADC_InitStruct->ADC_DataAlign));
assert_param(IS_ADC_REGULAR_LENGTH(ADC_InitStruct->ADC_NbrOfChannel));
/*---------------------------- ADCx CR1 Configuration -----------------*/
/* Get the ADCx CR1 value */
tmpreg1 = ADCx->CR1;
/* Clear DUALMOD and SCAN bits */
tmpreg1 &= CR1_CLEAR_Mask;
/* Configure ADCx: Dual mode and scan conversion mode */
/* Set DUALMOD bits according to ADC_Mode value */
/* Set SCAN bit according to ADC_ScanConvMode value */
tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_Mode | ((uint32_t)ADC_InitStruct->ADC_ScanConvMode << 8));
/* Write to ADCx CR1 */
ADCx->CR1 = tmpreg1;
/*---------------------------- ADCx CR2 Configuration -----------------*/
/* Get the ADCx CR2 value */
tmpreg1 = ADCx->CR2;
/* Clear CONT, ALIGN and EXTSEL bits */
tmpreg1 &= CR2_CLEAR_Mask;
/* Configure ADCx: external trigger event and continuous conversion mode */
/* Set ALIGN bit according to ADC_DataAlign value */
/* Set EXTSEL bits according to ADC_ExternalTrigConv value */
/* Set CONT bit according to ADC_ContinuousConvMode value */
tmpreg1 |= (uint32_t)(ADC_InitStruct->ADC_DataAlign | ADC_InitStruct->ADC_ExternalTrigConv |
((uint32_t)ADC_InitStruct->ADC_ContinuousConvMode << 1));
/* Write to ADCx CR2 */
ADCx->CR2 = tmpreg1;
/*---------------------------- ADCx SQR1 Configuration -----------------*/
/* Get the ADCx SQR1 value */
tmpreg1 = ADCx->SQR1;
/* Clear L bits */
tmpreg1 &= SQR1_CLEAR_Mask;
/* Configure ADCx: regular channel sequence length */
/* Set L bits according to ADC_NbrOfChannel value */
tmpreg2 |= (uint8_t) (ADC_InitStruct->ADC_NbrOfChannel - (uint8_t)1);
tmpreg1 |= (uint32_t)tmpreg2 << 20;
/* Write to ADCx SQR1 */
ADCx->SQR1 = tmpreg1;
}
/**
* @brief Fills each ADC_InitStruct member with its default value.
* @param ADC_InitStruct : pointer to an ADC_InitTypeDef structure which will be initialized.
* @retval None
*/
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct)
{
/* Reset ADC init structure parameters values */
/* Initialize the ADC_Mode member */
ADC_InitStruct->ADC_Mode = ADC_Mode_Independent;
/* initialize the ADC_ScanConvMode member */
ADC_InitStruct->ADC_ScanConvMode = DISABLE;
/* Initialize the ADC_ContinuousConvMode member */
ADC_InitStruct->ADC_ContinuousConvMode = DISABLE;
/* Initialize the ADC_ExternalTrigConv member */
ADC_InitStruct->ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
/* Initialize the ADC_DataAlign member */
ADC_InitStruct->ADC_DataAlign = ADC_DataAlign_Right;
/* Initialize the ADC_NbrOfChannel member */
ADC_InitStruct->ADC_NbrOfChannel = 1;
}
/**
* @brief Enables or disables the specified ADC peripheral.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param NewState: new state of the ADCx peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Set the ADON bit to wake up the ADC from power down mode */
ADCx->CR2 |= CR2_ADON_Set;
}
else
{
/* Disable the selected ADC peripheral */
ADCx->CR2 &= CR2_ADON_Reset;
}
}
/**
* @brief Enables or disables the specified ADC DMA request.
* @param ADCx: where x can be 1 or 3 to select the ADC peripheral.
* Note: ADC2 hasn't a DMA capability.
* @param NewState: new state of the selected ADC DMA transfer.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_DMA_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected ADC DMA request */
ADCx->CR2 |= CR2_DMA_Set;
}
else
{
/* Disable the selected ADC DMA request */
ADCx->CR2 &= CR2_DMA_Reset;
}
}
/**
* @brief Enables or disables the specified ADC interrupts.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_IT: specifies the ADC interrupt sources to be enabled or disabled.
* This parameter can be any combination of the following values:
* @arg ADC_IT_EOC: End of conversion interrupt mask
* @arg ADC_IT_AWD: Analog watchdog interrupt mask
* @arg ADC_IT_JEOC: End of injected conversion interrupt mask
* @param NewState: new state of the specified ADC interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState)
{
uint8_t itmask = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
assert_param(IS_ADC_IT(ADC_IT));
/* Get the ADC IT index */
itmask = (uint8_t)ADC_IT;
if (NewState != DISABLE)
{
/* Enable the selected ADC interrupts */
ADCx->CR1 |= itmask;
}
else
{
/* Disable the selected ADC interrupts */
ADCx->CR1 &= (~(uint32_t)itmask);
}
}
/**
* @brief Resets the selected ADC calibration registers.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @retval None
*/
void ADC_ResetCalibration(ADC_TypeDef* ADCx)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
/* Resets the selected ADC calibration registers */
ADCx->CR2 |= CR2_RSTCAL_Set;
}
/**
* @brief Gets the selected ADC reset calibration registers status.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @retval The new state of ADC reset calibration registers (SET or RESET).
*/
FlagStatus ADC_GetResetCalibrationStatus(ADC_TypeDef* ADCx)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
/* Check the status of RSTCAL bit */
if ((ADCx->CR2 & CR2_RSTCAL_Set) != (uint32_t)RESET)
{
/* RSTCAL bit is set */
bitstatus = SET;
}
else
{
/* RSTCAL bit is reset */
bitstatus = RESET;
}
/* Return the RSTCAL bit status */
return bitstatus;
}
/**
* @brief Starts the selected ADC calibration process.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @retval None
*/
void ADC_StartCalibration(ADC_TypeDef* ADCx)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
/* Enable the selected ADC calibration process */
ADCx->CR2 |= CR2_CAL_Set;
}
/**
* @brief Gets the selected ADC calibration status.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @retval The new state of ADC calibration (SET or RESET).
*/
FlagStatus ADC_GetCalibrationStatus(ADC_TypeDef* ADCx)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
/* Check the status of CAL bit */
if ((ADCx->CR2 & CR2_CAL_Set) != (uint32_t)RESET)
{
/* CAL bit is set: calibration on going */
bitstatus = SET;
}
else
{
/* CAL bit is reset: end of calibration */
bitstatus = RESET;
}
/* Return the CAL bit status */
return bitstatus;
}
/**
* @brief Enables or disables the selected ADC software start conversion .
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param NewState: new state of the selected ADC software start conversion.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_SoftwareStartConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected ADC conversion on external event and start the selected
ADC conversion */
ADCx->CR2 |= CR2_EXTTRIG_SWSTART_Set;
}
else
{
/* Disable the selected ADC conversion on external event and stop the selected
ADC conversion */
ADCx->CR2 &= CR2_EXTTRIG_SWSTART_Reset;
}
}
/**
* @brief Gets the selected ADC Software start conversion Status.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @retval The new state of ADC software start conversion (SET or RESET).
*/
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
/* Check the status of SWSTART bit */
if ((ADCx->CR2 & CR2_SWSTART_Set) != (uint32_t)RESET)
{
/* SWSTART bit is set */
bitstatus = SET;
}
else
{
/* SWSTART bit is reset */
bitstatus = RESET;
}
/* Return the SWSTART bit status */
return bitstatus;
}
/**
* @brief Configures the discontinuous mode for the selected ADC regular
* group channel.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param Number: specifies the discontinuous mode regular channel
* count value. This number must be between 1 and 8.
* @retval None
*/
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number)
{
uint32_t tmpreg1 = 0;
uint32_t tmpreg2 = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_REGULAR_DISC_NUMBER(Number));
/* Get the old register value */
tmpreg1 = ADCx->CR1;
/* Clear the old discontinuous mode channel count */
tmpreg1 &= CR1_DISCNUM_Reset;
/* Set the discontinuous mode channel count */
tmpreg2 = Number - 1;
tmpreg1 |= tmpreg2 << 13;
/* Store the new register value */
ADCx->CR1 = tmpreg1;
}
/**
* @brief Enables or disables the discontinuous mode on regular group
* channel for the specified ADC
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param NewState: new state of the selected ADC discontinuous mode
* on regular group channel.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected ADC regular discontinuous mode */
ADCx->CR1 |= CR1_DISCEN_Set;
}
else
{
/* Disable the selected ADC regular discontinuous mode */
ADCx->CR1 &= CR1_DISCEN_Reset;
}
}
/**
* @brief Configures for the selected ADC regular channel its corresponding
* rank in the sequencer and its sample time.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_Channel: the ADC channel to configure.
* This parameter can be one of the following values:
* @arg ADC_Channel_0: ADC Channel0 selected
* @arg ADC_Channel_1: ADC Channel1 selected
* @arg ADC_Channel_2: ADC Channel2 selected
* @arg ADC_Channel_3: ADC Channel3 selected
* @arg ADC_Channel_4: ADC Channel4 selected
* @arg ADC_Channel_5: ADC Channel5 selected
* @arg ADC_Channel_6: ADC Channel6 selected
* @arg ADC_Channel_7: ADC Channel7 selected
* @arg ADC_Channel_8: ADC Channel8 selected
* @arg ADC_Channel_9: ADC Channel9 selected
* @arg ADC_Channel_10: ADC Channel10 selected
* @arg ADC_Channel_11: ADC Channel11 selected
* @arg ADC_Channel_12: ADC Channel12 selected
* @arg ADC_Channel_13: ADC Channel13 selected
* @arg ADC_Channel_14: ADC Channel14 selected
* @arg ADC_Channel_15: ADC Channel15 selected
* @arg ADC_Channel_16: ADC Channel16 selected
* @arg ADC_Channel_17: ADC Channel17 selected
* @param Rank: The rank in the regular group sequencer. This parameter must be between 1 to 16.
* @param ADC_SampleTime: The sample time value to be set for the selected channel.
* This parameter can be one of the following values:
* @arg ADC_SampleTime_1Cycles5: Sample time equal to 1.5 cycles
* @arg ADC_SampleTime_7Cycles5: Sample time equal to 7.5 cycles
* @arg ADC_SampleTime_13Cycles5: Sample time equal to 13.5 cycles
* @arg ADC_SampleTime_28Cycles5: Sample time equal to 28.5 cycles
* @arg ADC_SampleTime_41Cycles5: Sample time equal to 41.5 cycles
* @arg ADC_SampleTime_55Cycles5: Sample time equal to 55.5 cycles
* @arg ADC_SampleTime_71Cycles5: Sample time equal to 71.5 cycles
* @arg ADC_SampleTime_239Cycles5: Sample time equal to 239.5 cycles
* @retval None
*/
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
{
uint32_t tmpreg1 = 0, tmpreg2 = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_CHANNEL(ADC_Channel));
assert_param(IS_ADC_REGULAR_RANK(Rank));
assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime));
/* if ADC_Channel_10 ... ADC_Channel_17 is selected */
if (ADC_Channel > ADC_Channel_9)
{
/* Get the old register value */
tmpreg1 = ADCx->SMPR1;
/* Calculate the mask to clear */
tmpreg2 = SMPR1_SMP_Set << (3 * (ADC_Channel - 10));
/* Clear the old channel sample time */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_SampleTime << (3 * (ADC_Channel - 10));
/* Set the new channel sample time */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SMPR1 = tmpreg1;
}
else /* ADC_Channel include in ADC_Channel_[0..9] */
{
/* Get the old register value */
tmpreg1 = ADCx->SMPR2;
/* Calculate the mask to clear */
tmpreg2 = SMPR2_SMP_Set << (3 * ADC_Channel);
/* Clear the old channel sample time */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel);
/* Set the new channel sample time */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SMPR2 = tmpreg1;
}
/* For Rank 1 to 6 */
if (Rank < 7)
{
/* Get the old register value */
tmpreg1 = ADCx->SQR3;
/* Calculate the mask to clear */
tmpreg2 = SQR3_SQ_Set << (5 * (Rank - 1));
/* Clear the old SQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 1));
/* Set the SQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SQR3 = tmpreg1;
}
/* For Rank 7 to 12 */
else if (Rank < 13)
{
/* Get the old register value */
tmpreg1 = ADCx->SQR2;
/* Calculate the mask to clear */
tmpreg2 = SQR2_SQ_Set << (5 * (Rank - 7));
/* Clear the old SQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 7));
/* Set the SQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SQR2 = tmpreg1;
}
/* For Rank 13 to 16 */
else
{
/* Get the old register value */
tmpreg1 = ADCx->SQR1;
/* Calculate the mask to clear */
tmpreg2 = SQR1_SQ_Set << (5 * (Rank - 13));
/* Clear the old SQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (Rank - 13));
/* Set the SQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SQR1 = tmpreg1;
}
}
/**
* @brief Enables or disables the ADCx conversion through external trigger.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param NewState: new state of the selected ADC external trigger start of conversion.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_ExternalTrigConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected ADC conversion on external event */
ADCx->CR2 |= CR2_EXTTRIG_Set;
}
else
{
/* Disable the selected ADC conversion on external event */
ADCx->CR2 &= CR2_EXTTRIG_Reset;
}
}
/**
* @brief Returns the last ADCx conversion result data for regular channel.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @retval The Data conversion value.
*/
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
/* Return the selected ADC conversion value */
return (uint16_t) ADCx->DR;
}
/**
* @brief Returns the last ADC1 and ADC2 conversion result data in dual mode.
* @retval The Data conversion value.
*/
uint32_t ADC_GetDualModeConversionValue(void)
{
/* Return the dual mode conversion value */
return (*(__IO uint32_t *) DR_ADDRESS);
}
/**
* @brief Enables or disables the selected ADC automatic injected group
* conversion after regular one.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param NewState: new state of the selected ADC auto injected conversion
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected ADC automatic injected group conversion */
ADCx->CR1 |= CR1_JAUTO_Set;
}
else
{
/* Disable the selected ADC automatic injected group conversion */
ADCx->CR1 &= CR1_JAUTO_Reset;
}
}
/**
* @brief Enables or disables the discontinuous mode for injected group
* channel for the specified ADC
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param NewState: new state of the selected ADC discontinuous mode
* on injected group channel.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected ADC injected discontinuous mode */
ADCx->CR1 |= CR1_JDISCEN_Set;
}
else
{
/* Disable the selected ADC injected discontinuous mode */
ADCx->CR1 &= CR1_JDISCEN_Reset;
}
}
/**
* @brief Configures the ADCx external trigger for injected channels conversion.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_ExternalTrigInjecConv: specifies the ADC trigger to start injected conversion.
* This parameter can be one of the following values:
* @arg ADC_ExternalTrigInjecConv_T1_TRGO: Timer1 TRGO event selected (for ADC1, ADC2 and ADC3)
* @arg ADC_ExternalTrigInjecConv_T1_CC4: Timer1 capture compare4 selected (for ADC1, ADC2 and ADC3)
* @arg ADC_ExternalTrigInjecConv_T2_TRGO: Timer2 TRGO event selected (for ADC1 and ADC2)
* @arg ADC_ExternalTrigInjecConv_T2_CC1: Timer2 capture compare1 selected (for ADC1 and ADC2)
* @arg ADC_ExternalTrigInjecConv_T3_CC4: Timer3 capture compare4 selected (for ADC1 and ADC2)
* @arg ADC_ExternalTrigInjecConv_T4_TRGO: Timer4 TRGO event selected (for ADC1 and ADC2)
* @arg ADC_ExternalTrigInjecConv_Ext_IT15_TIM8_CC4: External interrupt line 15 or Timer8
* capture compare4 event selected (for ADC1 and ADC2)
* @arg ADC_ExternalTrigInjecConv_T4_CC3: Timer4 capture compare3 selected (for ADC3 only)
* @arg ADC_ExternalTrigInjecConv_T8_CC2: Timer8 capture compare2 selected (for ADC3 only)
* @arg ADC_ExternalTrigInjecConv_T8_CC4: Timer8 capture compare4 selected (for ADC3 only)
* @arg ADC_ExternalTrigInjecConv_T5_TRGO: Timer5 TRGO event selected (for ADC3 only)
* @arg ADC_ExternalTrigInjecConv_T5_CC4: Timer5 capture compare4 selected (for ADC3 only)
* @arg ADC_ExternalTrigInjecConv_None: Injected conversion started by software and not
* by external trigger (for ADC1, ADC2 and ADC3)
* @retval None
*/
void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_EXT_INJEC_TRIG(ADC_ExternalTrigInjecConv));
/* Get the old register value */
tmpreg = ADCx->CR2;
/* Clear the old external event selection for injected group */
tmpreg &= CR2_JEXTSEL_Reset;
/* Set the external event selection for injected group */
tmpreg |= ADC_ExternalTrigInjecConv;
/* Store the new register value */
ADCx->CR2 = tmpreg;
}
/**
* @brief Enables or disables the ADCx injected channels conversion through
* external trigger
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param NewState: new state of the selected ADC external trigger start of
* injected conversion.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_ExternalTrigInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected ADC external event selection for injected group */
ADCx->CR2 |= CR2_JEXTTRIG_Set;
}
else
{
/* Disable the selected ADC external event selection for injected group */
ADCx->CR2 &= CR2_JEXTTRIG_Reset;
}
}
/**
* @brief Enables or disables the selected ADC start of the injected
* channels conversion.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param NewState: new state of the selected ADC software start injected conversion.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_SoftwareStartInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected ADC conversion for injected group on external event and start the selected
ADC injected conversion */
ADCx->CR2 |= CR2_JEXTTRIG_JSWSTART_Set;
}
else
{
/* Disable the selected ADC conversion on external event for injected group and stop the selected
ADC injected conversion */
ADCx->CR2 &= CR2_JEXTTRIG_JSWSTART_Reset;
}
}
/**
* @brief Gets the selected ADC Software start injected conversion Status.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @retval The new state of ADC software start injected conversion (SET or RESET).
*/
FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
/* Check the status of JSWSTART bit */
if ((ADCx->CR2 & CR2_JSWSTART_Set) != (uint32_t)RESET)
{
/* JSWSTART bit is set */
bitstatus = SET;
}
else
{
/* JSWSTART bit is reset */
bitstatus = RESET;
}
/* Return the JSWSTART bit status */
return bitstatus;
}
/**
* @brief Configures for the selected ADC injected channel its corresponding
* rank in the sequencer and its sample time.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_Channel: the ADC channel to configure.
* This parameter can be one of the following values:
* @arg ADC_Channel_0: ADC Channel0 selected
* @arg ADC_Channel_1: ADC Channel1 selected
* @arg ADC_Channel_2: ADC Channel2 selected
* @arg ADC_Channel_3: ADC Channel3 selected
* @arg ADC_Channel_4: ADC Channel4 selected
* @arg ADC_Channel_5: ADC Channel5 selected
* @arg ADC_Channel_6: ADC Channel6 selected
* @arg ADC_Channel_7: ADC Channel7 selected
* @arg ADC_Channel_8: ADC Channel8 selected
* @arg ADC_Channel_9: ADC Channel9 selected
* @arg ADC_Channel_10: ADC Channel10 selected
* @arg ADC_Channel_11: ADC Channel11 selected
* @arg ADC_Channel_12: ADC Channel12 selected
* @arg ADC_Channel_13: ADC Channel13 selected
* @arg ADC_Channel_14: ADC Channel14 selected
* @arg ADC_Channel_15: ADC Channel15 selected
* @arg ADC_Channel_16: ADC Channel16 selected
* @arg ADC_Channel_17: ADC Channel17 selected
* @param Rank: The rank in the injected group sequencer. This parameter must be between 1 and 4.
* @param ADC_SampleTime: The sample time value to be set for the selected channel.
* This parameter can be one of the following values:
* @arg ADC_SampleTime_1Cycles5: Sample time equal to 1.5 cycles
* @arg ADC_SampleTime_7Cycles5: Sample time equal to 7.5 cycles
* @arg ADC_SampleTime_13Cycles5: Sample time equal to 13.5 cycles
* @arg ADC_SampleTime_28Cycles5: Sample time equal to 28.5 cycles
* @arg ADC_SampleTime_41Cycles5: Sample time equal to 41.5 cycles
* @arg ADC_SampleTime_55Cycles5: Sample time equal to 55.5 cycles
* @arg ADC_SampleTime_71Cycles5: Sample time equal to 71.5 cycles
* @arg ADC_SampleTime_239Cycles5: Sample time equal to 239.5 cycles
* @retval None
*/
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime)
{
uint32_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_CHANNEL(ADC_Channel));
assert_param(IS_ADC_INJECTED_RANK(Rank));
assert_param(IS_ADC_SAMPLE_TIME(ADC_SampleTime));
/* if ADC_Channel_10 ... ADC_Channel_17 is selected */
if (ADC_Channel > ADC_Channel_9)
{
/* Get the old register value */
tmpreg1 = ADCx->SMPR1;
/* Calculate the mask to clear */
tmpreg2 = SMPR1_SMP_Set << (3*(ADC_Channel - 10));
/* Clear the old channel sample time */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_SampleTime << (3*(ADC_Channel - 10));
/* Set the new channel sample time */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SMPR1 = tmpreg1;
}
else /* ADC_Channel include in ADC_Channel_[0..9] */
{
/* Get the old register value */
tmpreg1 = ADCx->SMPR2;
/* Calculate the mask to clear */
tmpreg2 = SMPR2_SMP_Set << (3 * ADC_Channel);
/* Clear the old channel sample time */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set */
tmpreg2 = (uint32_t)ADC_SampleTime << (3 * ADC_Channel);
/* Set the new channel sample time */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->SMPR2 = tmpreg1;
}
/* Rank configuration */
/* Get the old register value */
tmpreg1 = ADCx->JSQR;
/* Get JL value: Number = JL+1 */
tmpreg3 = (tmpreg1 & JSQR_JL_Set)>> 20;
/* Calculate the mask to clear: ((Rank-1)+(4-JL-1)) */
tmpreg2 = JSQR_JSQ_Set << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1)));
/* Clear the old JSQx bits for the selected rank */
tmpreg1 &= ~tmpreg2;
/* Calculate the mask to set: ((Rank-1)+(4-JL-1)) */
tmpreg2 = (uint32_t)ADC_Channel << (5 * (uint8_t)((Rank + 3) - (tmpreg3 + 1)));
/* Set the JSQx bits for the selected rank */
tmpreg1 |= tmpreg2;
/* Store the new register value */
ADCx->JSQR = tmpreg1;
}
/**
* @brief Configures the sequencer length for injected channels
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param Length: The sequencer length.
* This parameter must be a number between 1 to 4.
* @retval None
*/
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length)
{
uint32_t tmpreg1 = 0;
uint32_t tmpreg2 = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_INJECTED_LENGTH(Length));
/* Get the old register value */
tmpreg1 = ADCx->JSQR;
/* Clear the old injected sequnence lenght JL bits */
tmpreg1 &= JSQR_JL_Reset;
/* Set the injected sequnence lenght JL bits */
tmpreg2 = Length - 1;
tmpreg1 |= tmpreg2 << 20;
/* Store the new register value */
ADCx->JSQR = tmpreg1;
}
/**
* @brief Set the injected channels conversion value offset
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_InjectedChannel: the ADC injected channel to set its offset.
* This parameter can be one of the following values:
* @arg ADC_InjectedChannel_1: Injected Channel1 selected
* @arg ADC_InjectedChannel_2: Injected Channel2 selected
* @arg ADC_InjectedChannel_3: Injected Channel3 selected
* @arg ADC_InjectedChannel_4: Injected Channel4 selected
* @param Offset: the offset value for the selected ADC injected channel
* This parameter must be a 12bit value.
* @retval None
*/
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset)
{
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel));
assert_param(IS_ADC_OFFSET(Offset));
tmp = (uint32_t)ADCx;
tmp += ADC_InjectedChannel;
/* Set the selected injected channel data offset */
*(__IO uint32_t *) tmp = (uint32_t)Offset;
}
/**
* @brief Returns the ADC injected channel conversion result
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_InjectedChannel: the converted ADC injected channel.
* This parameter can be one of the following values:
* @arg ADC_InjectedChannel_1: Injected Channel1 selected
* @arg ADC_InjectedChannel_2: Injected Channel2 selected
* @arg ADC_InjectedChannel_3: Injected Channel3 selected
* @arg ADC_InjectedChannel_4: Injected Channel4 selected
* @retval The Data conversion value.
*/
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel)
{
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel));
tmp = (uint32_t)ADCx;
tmp += ADC_InjectedChannel + JDR_Offset;
/* Returns the selected injected channel conversion data value */
return (uint16_t) (*(__IO uint32_t*) tmp);
}
/**
* @brief Enables or disables the analog watchdog on single/all regular
* or injected channels
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_AnalogWatchdog: the ADC analog watchdog configuration.
* This parameter can be one of the following values:
* @arg ADC_AnalogWatchdog_SingleRegEnable: Analog watchdog on a single regular channel
* @arg ADC_AnalogWatchdog_SingleInjecEnable: Analog watchdog on a single injected channel
* @arg ADC_AnalogWatchdog_SingleRegOrInjecEnable: Analog watchdog on a single regular or injected channel
* @arg ADC_AnalogWatchdog_AllRegEnable: Analog watchdog on all regular channel
* @arg ADC_AnalogWatchdog_AllInjecEnable: Analog watchdog on all injected channel
* @arg ADC_AnalogWatchdog_AllRegAllInjecEnable: Analog watchdog on all regular and injected channels
* @arg ADC_AnalogWatchdog_None: No channel guarded by the analog watchdog
* @retval None
*/
void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_ANALOG_WATCHDOG(ADC_AnalogWatchdog));
/* Get the old register value */
tmpreg = ADCx->CR1;
/* Clear AWDEN, AWDENJ and AWDSGL bits */
tmpreg &= CR1_AWDMode_Reset;
/* Set the analog watchdog enable mode */
tmpreg |= ADC_AnalogWatchdog;
/* Store the new register value */
ADCx->CR1 = tmpreg;
}
/**
* @brief Configures the high and low thresholds of the analog watchdog.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param HighThreshold: the ADC analog watchdog High threshold value.
* This parameter must be a 12bit value.
* @param LowThreshold: the ADC analog watchdog Low threshold value.
* This parameter must be a 12bit value.
* @retval None
*/
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,
uint16_t LowThreshold)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_THRESHOLD(HighThreshold));
assert_param(IS_ADC_THRESHOLD(LowThreshold));
/* Set the ADCx high threshold */
ADCx->HTR = HighThreshold;
/* Set the ADCx low threshold */
ADCx->LTR = LowThreshold;
}
/**
* @brief Configures the analog watchdog guarded single channel
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_Channel: the ADC channel to configure for the analog watchdog.
* This parameter can be one of the following values:
* @arg ADC_Channel_0: ADC Channel0 selected
* @arg ADC_Channel_1: ADC Channel1 selected
* @arg ADC_Channel_2: ADC Channel2 selected
* @arg ADC_Channel_3: ADC Channel3 selected
* @arg ADC_Channel_4: ADC Channel4 selected
* @arg ADC_Channel_5: ADC Channel5 selected
* @arg ADC_Channel_6: ADC Channel6 selected
* @arg ADC_Channel_7: ADC Channel7 selected
* @arg ADC_Channel_8: ADC Channel8 selected
* @arg ADC_Channel_9: ADC Channel9 selected
* @arg ADC_Channel_10: ADC Channel10 selected
* @arg ADC_Channel_11: ADC Channel11 selected
* @arg ADC_Channel_12: ADC Channel12 selected
* @arg ADC_Channel_13: ADC Channel13 selected
* @arg ADC_Channel_14: ADC Channel14 selected
* @arg ADC_Channel_15: ADC Channel15 selected
* @arg ADC_Channel_16: ADC Channel16 selected
* @arg ADC_Channel_17: ADC Channel17 selected
* @retval None
*/
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_CHANNEL(ADC_Channel));
/* Get the old register value */
tmpreg = ADCx->CR1;
/* Clear the Analog watchdog channel select bits */
tmpreg &= CR1_AWDCH_Reset;
/* Set the Analog watchdog channel */
tmpreg |= ADC_Channel;
/* Store the new register value */
ADCx->CR1 = tmpreg;
}
/**
* @brief Enables or disables the temperature sensor and Vrefint channel.
* @param NewState: new state of the temperature sensor.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void ADC_TempSensorVrefintCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the temperature sensor and Vrefint channel*/
ADC1->CR2 |= CR2_TSVREFE_Set;
}
else
{
/* Disable the temperature sensor and Vrefint channel*/
ADC1->CR2 &= CR2_TSVREFE_Reset;
}
}
/**
* @brief Checks whether the specified ADC flag is set or not.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_FLAG: specifies the flag to check.
* This parameter can be one of the following values:
* @arg ADC_FLAG_AWD: Analog watchdog flag
* @arg ADC_FLAG_EOC: End of conversion flag
* @arg ADC_FLAG_JEOC: End of injected group conversion flag
* @arg ADC_FLAG_JSTRT: Start of injected group conversion flag
* @arg ADC_FLAG_STRT: Start of regular group conversion flag
* @retval The new state of ADC_FLAG (SET or RESET).
*/
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_GET_FLAG(ADC_FLAG));
/* Check the status of the specified ADC flag */
if ((ADCx->SR & ADC_FLAG) != (uint8_t)RESET)
{
/* ADC_FLAG is set */
bitstatus = SET;
}
else
{
/* ADC_FLAG is reset */
bitstatus = RESET;
}
/* Return the ADC_FLAG status */
return bitstatus;
}
/**
* @brief Clears the ADCx's pending flags.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_FLAG: specifies the flag to clear.
* This parameter can be any combination of the following values:
* @arg ADC_FLAG_AWD: Analog watchdog flag
* @arg ADC_FLAG_EOC: End of conversion flag
* @arg ADC_FLAG_JEOC: End of injected group conversion flag
* @arg ADC_FLAG_JSTRT: Start of injected group conversion flag
* @arg ADC_FLAG_STRT: Start of regular group conversion flag
* @retval None
*/
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint8_t ADC_FLAG)
{
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_CLEAR_FLAG(ADC_FLAG));
/* Clear the selected ADC flags */
ADCx->SR = ~(uint32_t)ADC_FLAG;
}
/**
* @brief Checks whether the specified ADC interrupt has occurred or not.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_IT: specifies the ADC interrupt source to check.
* This parameter can be one of the following values:
* @arg ADC_IT_EOC: End of conversion interrupt mask
* @arg ADC_IT_AWD: Analog watchdog interrupt mask
* @arg ADC_IT_JEOC: End of injected conversion interrupt mask
* @retval The new state of ADC_IT (SET or RESET).
*/
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT)
{
ITStatus bitstatus = RESET;
uint32_t itmask = 0, enablestatus = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_GET_IT(ADC_IT));
/* Get the ADC IT index */
itmask = ADC_IT >> 8;
/* Get the ADC_IT enable bit status */
enablestatus = (ADCx->CR1 & (uint8_t)ADC_IT) ;
/* Check the status of the specified ADC interrupt */
if (((ADCx->SR & itmask) != (uint32_t)RESET) && enablestatus)
{
/* ADC_IT is set */
bitstatus = SET;
}
else
{
/* ADC_IT is reset */
bitstatus = RESET;
}
/* Return the ADC_IT status */
return bitstatus;
}
/**
* @brief Clears the ADCx's interrupt pending bits.
* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.
* @param ADC_IT: specifies the ADC interrupt pending bit to clear.
* This parameter can be any combination of the following values:
* @arg ADC_IT_EOC: End of conversion interrupt mask
* @arg ADC_IT_AWD: Analog watchdog interrupt mask
* @arg ADC_IT_JEOC: End of injected conversion interrupt mask
* @retval None
*/
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT)
{
uint8_t itmask = 0;
/* Check the parameters */
assert_param(IS_ADC_ALL_PERIPH(ADCx));
assert_param(IS_ADC_IT(ADC_IT));
/* Get the ADC IT index */
itmask = (uint8_t)(ADC_IT >> 8);
/* Clear the selected ADC interrupt pending bits */
ADCx->SR = ~(uint32_t)itmask;
}
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_bkp.c
================================================
/**
******************************************************************************
* @file stm32f10x_bkp.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the BKP firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_bkp.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup BKP
* @brief BKP driver modules
* @{
*/
/** @defgroup BKP_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup BKP_Private_Defines
* @{
*/
/* ------------ BKP registers bit address in the alias region --------------- */
#define BKP_OFFSET (BKP_BASE - PERIPH_BASE)
/* --- CR Register ----*/
/* Alias word address of TPAL bit */
#define CR_OFFSET (BKP_OFFSET + 0x30)
#define TPAL_BitNumber 0x01
#define CR_TPAL_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (TPAL_BitNumber * 4))
/* Alias word address of TPE bit */
#define TPE_BitNumber 0x00
#define CR_TPE_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (TPE_BitNumber * 4))
/* --- CSR Register ---*/
/* Alias word address of TPIE bit */
#define CSR_OFFSET (BKP_OFFSET + 0x34)
#define TPIE_BitNumber 0x02
#define CSR_TPIE_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TPIE_BitNumber * 4))
/* Alias word address of TIF bit */
#define TIF_BitNumber 0x09
#define CSR_TIF_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TIF_BitNumber * 4))
/* Alias word address of TEF bit */
#define TEF_BitNumber 0x08
#define CSR_TEF_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TEF_BitNumber * 4))
/* ---------------------- BKP registers bit mask ------------------------ */
/* RTCCR register bit mask */
#define RTCCR_CAL_MASK ((uint16_t)0xFF80)
#define RTCCR_MASK ((uint16_t)0xFC7F)
/**
* @}
*/
/** @defgroup BKP_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup BKP_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup BKP_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup BKP_Private_Functions
* @{
*/
/**
* @brief Deinitializes the BKP peripheral registers to their default reset values.
* @param None
* @retval None
*/
void BKP_DeInit(void)
{
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);
}
/**
* @brief Configures the Tamper Pin active level.
* @param BKP_TamperPinLevel: specifies the Tamper Pin active level.
* This parameter can be one of the following values:
* @arg BKP_TamperPinLevel_High: Tamper pin active on high level
* @arg BKP_TamperPinLevel_Low: Tamper pin active on low level
* @retval None
*/
void BKP_TamperPinLevelConfig(uint16_t BKP_TamperPinLevel)
{
/* Check the parameters */
assert_param(IS_BKP_TAMPER_PIN_LEVEL(BKP_TamperPinLevel));
*(__IO uint32_t *) CR_TPAL_BB = BKP_TamperPinLevel;
}
/**
* @brief Enables or disables the Tamper Pin activation.
* @param NewState: new state of the Tamper Pin activation.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void BKP_TamperPinCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CR_TPE_BB = (uint32_t)NewState;
}
/**
* @brief Enables or disables the Tamper Pin Interrupt.
* @param NewState: new state of the Tamper Pin Interrupt.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void BKP_ITConfig(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CSR_TPIE_BB = (uint32_t)NewState;
}
/**
* @brief Select the RTC output source to output on the Tamper pin.
* @param BKP_RTCOutputSource: specifies the RTC output source.
* This parameter can be one of the following values:
* @arg BKP_RTCOutputSource_None: no RTC output on the Tamper pin.
* @arg BKP_RTCOutputSource_CalibClock: output the RTC clock with frequency
* divided by 64 on the Tamper pin.
* @arg BKP_RTCOutputSource_Alarm: output the RTC Alarm pulse signal on
* the Tamper pin.
* @arg BKP_RTCOutputSource_Second: output the RTC Second pulse signal on
* the Tamper pin.
* @retval None
*/
void BKP_RTCOutputConfig(uint16_t BKP_RTCOutputSource)
{
uint16_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_BKP_RTC_OUTPUT_SOURCE(BKP_RTCOutputSource));
tmpreg = BKP->RTCCR;
/* Clear CCO, ASOE and ASOS bits */
tmpreg &= RTCCR_MASK;
/* Set CCO, ASOE and ASOS bits according to BKP_RTCOutputSource value */
tmpreg |= BKP_RTCOutputSource;
/* Store the new value */
BKP->RTCCR = tmpreg;
}
/**
* @brief Sets RTC Clock Calibration value.
* @param CalibrationValue: specifies the RTC Clock Calibration value.
* This parameter must be a number between 0 and 0x7F.
* @retval None
*/
void BKP_SetRTCCalibrationValue(uint8_t CalibrationValue)
{
uint16_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_BKP_CALIBRATION_VALUE(CalibrationValue));
tmpreg = BKP->RTCCR;
/* Clear CAL[6:0] bits */
tmpreg &= RTCCR_CAL_MASK;
/* Set CAL[6:0] bits according to CalibrationValue value */
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
tmpreg |= CalibrationValue;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/* Store the new value */
BKP->RTCCR = tmpreg;
}
/**
* @brief Writes user data to the specified Data Backup Register.
* @param BKP_DR: specifies the Data Backup Register.
* This parameter can be BKP_DRx where x:[1, 42]
* @param Data: data to write
* @retval None
*/
void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data)
{
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_BKP_DR(BKP_DR));
tmp = (uint32_t)BKP_BASE;
tmp += BKP_DR;
*(__IO uint32_t *) tmp = Data;
}
/**
* @brief Reads data from the specified Data Backup Register.
* @param BKP_DR: specifies the Data Backup Register.
* This parameter can be BKP_DRx where x:[1, 42]
* @retval The content of the specified Data Backup Register
*/
uint16_t BKP_ReadBackupRegister(uint16_t BKP_DR)
{
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_BKP_DR(BKP_DR));
tmp = (uint32_t)BKP_BASE;
tmp += BKP_DR;
return (*(__IO uint16_t *) tmp);
}
/**
* @brief Checks whether the Tamper Pin Event flag is set or not.
* @param None
* @retval The new state of the Tamper Pin Event flag (SET or RESET).
*/
FlagStatus BKP_GetFlagStatus(void)
{
return (FlagStatus)(*(__IO uint32_t *) CSR_TEF_BB);
}
/**
* @brief Clears Tamper Pin Event pending flag.
* @param None
* @retval None
*/
void BKP_ClearFlag(void)
{
/* Set CTE bit to clear Tamper Pin Event flag */
BKP->CSR |= BKP_CSR_CTE;
}
/**
* @brief Checks whether the Tamper Pin Interrupt has occurred or not.
* @param None
* @retval The new state of the Tamper Pin Interrupt (SET or RESET).
*/
ITStatus BKP_GetITStatus(void)
{
return (ITStatus)(*(__IO uint32_t *) CSR_TIF_BB);
}
/**
* @brief Clears Tamper Pin Interrupt pending bit.
* @param None
* @retval None
*/
void BKP_ClearITPendingBit(void)
{
/* Set CTI bit to clear Tamper Pin Interrupt pending bit */
BKP->CSR |= BKP_CSR_CTI;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_can.c
================================================
/**
******************************************************************************
* @file stm32f10x_can.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the CAN firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_can.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup CAN
* @brief CAN driver modules
* @{
*/
/** @defgroup CAN_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup CAN_Private_Defines
* @{
*/
/* CAN Master Control Register bits */
#define MCR_DBF ((uint32_t)0x00010000) /* software master reset */
/* CAN Mailbox Transmit Request */
#define TMIDxR_TXRQ ((uint32_t)0x00000001) /* Transmit mailbox request */
/* CAN Filter Master Register bits */
#define FMR_FINIT ((uint32_t)0x00000001) /* Filter init mode */
/* Time out for INAK bit */
#define INAK_TIMEOUT ((uint32_t)0x0000FFFF)
/* Time out for SLAK bit */
#define SLAK_TIMEOUT ((uint32_t)0x0000FFFF)
/* Flags in TSR register */
#define CAN_FLAGS_TSR ((uint32_t)0x08000000)
/* Flags in RF1R register */
#define CAN_FLAGS_RF1R ((uint32_t)0x04000000)
/* Flags in RF0R register */
#define CAN_FLAGS_RF0R ((uint32_t)0x02000000)
/* Flags in MSR register */
#define CAN_FLAGS_MSR ((uint32_t)0x01000000)
/* Flags in ESR register */
#define CAN_FLAGS_ESR ((uint32_t)0x00F00000)
/* Mailboxes definition */
#define CAN_TXMAILBOX_0 ((uint8_t)0x00)
#define CAN_TXMAILBOX_1 ((uint8_t)0x01)
#define CAN_TXMAILBOX_2 ((uint8_t)0x02)
#define CAN_MODE_MASK ((uint32_t) 0x00000003)
/**
* @}
*/
/** @defgroup CAN_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup CAN_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup CAN_Private_FunctionPrototypes
* @{
*/
static ITStatus CheckITStatus(uint32_t CAN_Reg, uint32_t It_Bit);
/**
* @}
*/
/** @defgroup CAN_Private_Functions
* @{
*/
/**
* @brief Deinitializes the CAN peripheral registers to their default reset values.
* @param CANx: where x can be 1 or 2 to select the CAN peripheral.
* @retval None.
*/
void CAN_DeInit(CAN_TypeDef* CANx)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
if (CANx == CAN1)
{
/* Enable CAN1 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, ENABLE);
/* Release CAN1 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN1, DISABLE);
}
else
{
/* Enable CAN2 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN2, ENABLE);
/* Release CAN2 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CAN2, DISABLE);
}
}
/**
* @brief Initializes the CAN peripheral according to the specified
* parameters in the CAN_InitStruct.
* @param CANx: where x can be 1 or 2 to to select the CAN
* peripheral.
* @param CAN_InitStruct: pointer to a CAN_InitTypeDef structure that
* contains the configuration information for the
* CAN peripheral.
* @retval Constant indicates initialization succeed which will be
* CAN_InitStatus_Failed or CAN_InitStatus_Success.
*/
uint8_t CAN_Init(CAN_TypeDef* CANx, CAN_InitTypeDef* CAN_InitStruct)
{
uint8_t InitStatus = CAN_InitStatus_Failed;
uint32_t wait_ack = 0x00000000;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_TTCM));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_ABOM));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_AWUM));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_NART));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_RFLM));
assert_param(IS_FUNCTIONAL_STATE(CAN_InitStruct->CAN_TXFP));
assert_param(IS_CAN_MODE(CAN_InitStruct->CAN_Mode));
assert_param(IS_CAN_SJW(CAN_InitStruct->CAN_SJW));
assert_param(IS_CAN_BS1(CAN_InitStruct->CAN_BS1));
assert_param(IS_CAN_BS2(CAN_InitStruct->CAN_BS2));
assert_param(IS_CAN_PRESCALER(CAN_InitStruct->CAN_Prescaler));
/* Exit from sleep mode */
CANx->MCR &= (~(uint32_t)CAN_MCR_SLEEP);
/* Request initialisation */
CANx->MCR |= CAN_MCR_INRQ ;
/* Wait the acknowledge */
while (((CANx->MSR & CAN_MSR_INAK) != CAN_MSR_INAK) && (wait_ack != INAK_TIMEOUT))
{
wait_ack++;
}
/* Check acknowledge */
if ((CANx->MSR & CAN_MSR_INAK) != CAN_MSR_INAK)
{
InitStatus = CAN_InitStatus_Failed;
}
else
{
/* Set the time triggered communication mode */
if (CAN_InitStruct->CAN_TTCM == ENABLE)
{
CANx->MCR |= CAN_MCR_TTCM;
}
else
{
CANx->MCR &= ~(uint32_t)CAN_MCR_TTCM;
}
/* Set the automatic bus-off management */
if (CAN_InitStruct->CAN_ABOM == ENABLE)
{
CANx->MCR |= CAN_MCR_ABOM;
}
else
{
CANx->MCR &= ~(uint32_t)CAN_MCR_ABOM;
}
/* Set the automatic wake-up mode */
if (CAN_InitStruct->CAN_AWUM == ENABLE)
{
CANx->MCR |= CAN_MCR_AWUM;
}
else
{
CANx->MCR &= ~(uint32_t)CAN_MCR_AWUM;
}
/* Set the no automatic retransmission */
if (CAN_InitStruct->CAN_NART == ENABLE)
{
CANx->MCR |= CAN_MCR_NART;
}
else
{
CANx->MCR &= ~(uint32_t)CAN_MCR_NART;
}
/* Set the receive FIFO locked mode */
if (CAN_InitStruct->CAN_RFLM == ENABLE)
{
CANx->MCR |= CAN_MCR_RFLM;
}
else
{
CANx->MCR &= ~(uint32_t)CAN_MCR_RFLM;
}
/* Set the transmit FIFO priority */
if (CAN_InitStruct->CAN_TXFP == ENABLE)
{
CANx->MCR |= CAN_MCR_TXFP;
}
else
{
CANx->MCR &= ~(uint32_t)CAN_MCR_TXFP;
}
/* Set the bit timing register */
CANx->BTR = (uint32_t)((uint32_t)CAN_InitStruct->CAN_Mode << 30) | \
((uint32_t)CAN_InitStruct->CAN_SJW << 24) | \
((uint32_t)CAN_InitStruct->CAN_BS1 << 16) | \
((uint32_t)CAN_InitStruct->CAN_BS2 << 20) | \
((uint32_t)CAN_InitStruct->CAN_Prescaler - 1);
/* Request leave initialisation */
CANx->MCR &= ~(uint32_t)CAN_MCR_INRQ;
/* Wait the acknowledge */
wait_ack = 0;
while (((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) && (wait_ack != INAK_TIMEOUT))
{
wait_ack++;
}
/* ...and check acknowledged */
if ((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
{
InitStatus = CAN_InitStatus_Failed;
}
else
{
InitStatus = CAN_InitStatus_Success ;
}
}
/* At this step, return the status of initialization */
return InitStatus;
}
/**
* @brief Initializes the CAN peripheral according to the specified
* parameters in the CAN_FilterInitStruct.
* @param CAN_FilterInitStruct: pointer to a CAN_FilterInitTypeDef
* structure that contains the configuration
* information.
* @retval None.
*/
void CAN_FilterInit(CAN_FilterInitTypeDef* CAN_FilterInitStruct)
{
uint32_t filter_number_bit_pos = 0;
/* Check the parameters */
assert_param(IS_CAN_FILTER_NUMBER(CAN_FilterInitStruct->CAN_FilterNumber));
assert_param(IS_CAN_FILTER_MODE(CAN_FilterInitStruct->CAN_FilterMode));
assert_param(IS_CAN_FILTER_SCALE(CAN_FilterInitStruct->CAN_FilterScale));
assert_param(IS_CAN_FILTER_FIFO(CAN_FilterInitStruct->CAN_FilterFIFOAssignment));
assert_param(IS_FUNCTIONAL_STATE(CAN_FilterInitStruct->CAN_FilterActivation));
filter_number_bit_pos = ((uint32_t)1) << CAN_FilterInitStruct->CAN_FilterNumber;
/* Initialisation mode for the filter */
CAN1->FMR |= FMR_FINIT;
/* Filter Deactivation */
CAN1->FA1R &= ~(uint32_t)filter_number_bit_pos;
/* Filter Scale */
if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_16bit)
{
/* 16-bit scale for the filter */
CAN1->FS1R &= ~(uint32_t)filter_number_bit_pos;
/* First 16-bit identifier and First 16-bit mask */
/* Or First 16-bit identifier and Second 16-bit identifier */
CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 =
((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow) << 16) |
(0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow);
/* Second 16-bit identifier and Second 16-bit mask */
/* Or Third 16-bit identifier and Fourth 16-bit identifier */
CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 =
((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) |
(0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh);
}
if (CAN_FilterInitStruct->CAN_FilterScale == CAN_FilterScale_32bit)
{
/* 32-bit scale for the filter */
CAN1->FS1R |= filter_number_bit_pos;
/* 32-bit identifier or First 32-bit identifier */
CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR1 =
((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdHigh) << 16) |
(0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterIdLow);
/* 32-bit mask or Second 32-bit identifier */
CAN1->sFilterRegister[CAN_FilterInitStruct->CAN_FilterNumber].FR2 =
((0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdHigh) << 16) |
(0x0000FFFF & (uint32_t)CAN_FilterInitStruct->CAN_FilterMaskIdLow);
}
/* Filter Mode */
if (CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdMask)
{
/*Id/Mask mode for the filter*/
CAN1->FM1R &= ~(uint32_t)filter_number_bit_pos;
}
else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
{
/*Identifier list mode for the filter*/
CAN1->FM1R |= (uint32_t)filter_number_bit_pos;
}
/* Filter FIFO assignment */
if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO0)
{
/* FIFO 0 assignation for the filter */
CAN1->FFA1R &= ~(uint32_t)filter_number_bit_pos;
}
if (CAN_FilterInitStruct->CAN_FilterFIFOAssignment == CAN_Filter_FIFO1)
{
/* FIFO 1 assignation for the filter */
CAN1->FFA1R |= (uint32_t)filter_number_bit_pos;
}
/* Filter activation */
if (CAN_FilterInitStruct->CAN_FilterActivation == ENABLE)
{
CAN1->FA1R |= filter_number_bit_pos;
}
/* Leave the initialisation mode for the filter */
CAN1->FMR &= ~FMR_FINIT;
}
/**
* @brief Fills each CAN_InitStruct member with its default value.
* @param CAN_InitStruct: pointer to a CAN_InitTypeDef structure which
* will be initialized.
* @retval None.
*/
void CAN_StructInit(CAN_InitTypeDef* CAN_InitStruct)
{
/* Reset CAN init structure parameters values */
/* Initialize the time triggered communication mode */
CAN_InitStruct->CAN_TTCM = DISABLE;
/* Initialize the automatic bus-off management */
CAN_InitStruct->CAN_ABOM = DISABLE;
/* Initialize the automatic wake-up mode */
CAN_InitStruct->CAN_AWUM = DISABLE;
/* Initialize the no automatic retransmission */
CAN_InitStruct->CAN_NART = DISABLE;
/* Initialize the receive FIFO locked mode */
CAN_InitStruct->CAN_RFLM = DISABLE;
/* Initialize the transmit FIFO priority */
CAN_InitStruct->CAN_TXFP = DISABLE;
/* Initialize the CAN_Mode member */
CAN_InitStruct->CAN_Mode = CAN_Mode_Normal;
/* Initialize the CAN_SJW member */
CAN_InitStruct->CAN_SJW = CAN_SJW_1tq;
/* Initialize the CAN_BS1 member */
CAN_InitStruct->CAN_BS1 = CAN_BS1_4tq;
/* Initialize the CAN_BS2 member */
CAN_InitStruct->CAN_BS2 = CAN_BS2_3tq;
/* Initialize the CAN_Prescaler member */
CAN_InitStruct->CAN_Prescaler = 1;
}
/**
* @brief Select the start bank filter for slave CAN.
* @note This function applies only to STM32 Connectivity line devices.
* @param CAN_BankNumber: Select the start slave bank filter from 1..27.
* @retval None.
*/
void CAN_SlaveStartBank(uint8_t CAN_BankNumber)
{
/* Check the parameters */
assert_param(IS_CAN_BANKNUMBER(CAN_BankNumber));
/* Enter Initialisation mode for the filter */
CAN1->FMR |= FMR_FINIT;
/* Select the start slave bank */
CAN1->FMR &= (uint32_t)0xFFFFC0F1 ;
CAN1->FMR |= (uint32_t)(CAN_BankNumber)<<8;
/* Leave Initialisation mode for the filter */
CAN1->FMR &= ~FMR_FINIT;
}
/**
* @brief Enables or disables the DBG Freeze for CAN.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param NewState: new state of the CAN peripheral. This parameter can
* be: ENABLE or DISABLE.
* @retval None.
*/
void CAN_DBGFreeze(CAN_TypeDef* CANx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable Debug Freeze */
CANx->MCR |= MCR_DBF;
}
else
{
/* Disable Debug Freeze */
CANx->MCR &= ~MCR_DBF;
}
}
/**
* @brief Enables or disabes the CAN Time TriggerOperation communication mode.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param NewState : Mode new state , can be one of @ref FunctionalState.
* @note when enabled, Time stamp (TIME[15:0]) value is sent in the last
* two data bytes of the 8-byte message: TIME[7:0] in data byte 6
* and TIME[15:8] in data byte 7
* @note DLC must be programmed as 8 in order Time Stamp (2 bytes) to be
* sent over the CAN bus.
* @retval None
*/
void CAN_TTComModeCmd(CAN_TypeDef* CANx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the TTCM mode */
CANx->MCR |= CAN_MCR_TTCM;
/* Set TGT bits */
CANx->sTxMailBox[0].TDTR |= ((uint32_t)CAN_TDT0R_TGT);
CANx->sTxMailBox[1].TDTR |= ((uint32_t)CAN_TDT1R_TGT);
CANx->sTxMailBox[2].TDTR |= ((uint32_t)CAN_TDT2R_TGT);
}
else
{
/* Disable the TTCM mode */
CANx->MCR &= (uint32_t)(~(uint32_t)CAN_MCR_TTCM);
/* Reset TGT bits */
CANx->sTxMailBox[0].TDTR &= ((uint32_t)~CAN_TDT0R_TGT);
CANx->sTxMailBox[1].TDTR &= ((uint32_t)~CAN_TDT1R_TGT);
CANx->sTxMailBox[2].TDTR &= ((uint32_t)~CAN_TDT2R_TGT);
}
}
/**
* @brief Initiates the transmission of a message.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param TxMessage: pointer to a structure which contains CAN Id, CAN
* DLC and CAN data.
* @retval The number of the mailbox that is used for transmission
* or CAN_TxStatus_NoMailBox if there is no empty mailbox.
*/
uint8_t CAN_Transmit(CAN_TypeDef* CANx, CanTxMsg* TxMessage)
{
uint8_t transmit_mailbox = 0;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_IDTYPE(TxMessage->IDE));
assert_param(IS_CAN_RTR(TxMessage->RTR));
assert_param(IS_CAN_DLC(TxMessage->DLC));
/* Select one empty transmit mailbox */
if ((CANx->TSR&CAN_TSR_TME0) == CAN_TSR_TME0)
{
transmit_mailbox = 0;
}
else if ((CANx->TSR&CAN_TSR_TME1) == CAN_TSR_TME1)
{
transmit_mailbox = 1;
}
else if ((CANx->TSR&CAN_TSR_TME2) == CAN_TSR_TME2)
{
transmit_mailbox = 2;
}
else
{
transmit_mailbox = CAN_TxStatus_NoMailBox;
}
if (transmit_mailbox != CAN_TxStatus_NoMailBox)
{
/* Set up the Id */
CANx->sTxMailBox[transmit_mailbox].TIR &= TMIDxR_TXRQ;
if (TxMessage->IDE == CAN_Id_Standard)
{
assert_param(IS_CAN_STDID(TxMessage->StdId));
CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->StdId << 21) | \
TxMessage->RTR);
}
else
{
assert_param(IS_CAN_EXTID(TxMessage->ExtId));
CANx->sTxMailBox[transmit_mailbox].TIR |= ((TxMessage->ExtId << 3) | \
TxMessage->IDE | \
TxMessage->RTR);
}
/* Set up the DLC */
TxMessage->DLC &= (uint8_t)0x0000000F;
CANx->sTxMailBox[transmit_mailbox].TDTR &= (uint32_t)0xFFFFFFF0;
CANx->sTxMailBox[transmit_mailbox].TDTR |= TxMessage->DLC;
/* Set up the data field */
CANx->sTxMailBox[transmit_mailbox].TDLR = (((uint32_t)TxMessage->Data[3] << 24) |
((uint32_t)TxMessage->Data[2] << 16) |
((uint32_t)TxMessage->Data[1] << 8) |
((uint32_t)TxMessage->Data[0]));
CANx->sTxMailBox[transmit_mailbox].TDHR = (((uint32_t)TxMessage->Data[7] << 24) |
((uint32_t)TxMessage->Data[6] << 16) |
((uint32_t)TxMessage->Data[5] << 8) |
((uint32_t)TxMessage->Data[4]));
/* Request transmission */
CANx->sTxMailBox[transmit_mailbox].TIR |= TMIDxR_TXRQ;
}
return transmit_mailbox;
}
/**
* @brief Checks the transmission of a message.
* @param CANx: where x can be 1 or 2 to to select the
* CAN peripheral.
* @param TransmitMailbox: the number of the mailbox that is used for
* transmission.
* @retval CAN_TxStatus_Ok if the CAN driver transmits the message, CAN_TxStatus_Failed
* in an other case.
*/
uint8_t CAN_TransmitStatus(CAN_TypeDef* CANx, uint8_t TransmitMailbox)
{
uint32_t state = 0;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_TRANSMITMAILBOX(TransmitMailbox));
switch (TransmitMailbox)
{
case (CAN_TXMAILBOX_0):
state = CANx->TSR & (CAN_TSR_RQCP0 | CAN_TSR_TXOK0 | CAN_TSR_TME0);
break;
case (CAN_TXMAILBOX_1):
state = CANx->TSR & (CAN_TSR_RQCP1 | CAN_TSR_TXOK1 | CAN_TSR_TME1);
break;
case (CAN_TXMAILBOX_2):
state = CANx->TSR & (CAN_TSR_RQCP2 | CAN_TSR_TXOK2 | CAN_TSR_TME2);
break;
default:
state = CAN_TxStatus_Failed;
break;
}
switch (state)
{
/* transmit pending */
case (0x0): state = CAN_TxStatus_Pending;
break;
/* transmit failed */
case (CAN_TSR_RQCP0 | CAN_TSR_TME0): state = CAN_TxStatus_Failed;
break;
case (CAN_TSR_RQCP1 | CAN_TSR_TME1): state = CAN_TxStatus_Failed;
break;
case (CAN_TSR_RQCP2 | CAN_TSR_TME2): state = CAN_TxStatus_Failed;
break;
/* transmit succeeded */
case (CAN_TSR_RQCP0 | CAN_TSR_TXOK0 | CAN_TSR_TME0):state = CAN_TxStatus_Ok;
break;
case (CAN_TSR_RQCP1 | CAN_TSR_TXOK1 | CAN_TSR_TME1):state = CAN_TxStatus_Ok;
break;
case (CAN_TSR_RQCP2 | CAN_TSR_TXOK2 | CAN_TSR_TME2):state = CAN_TxStatus_Ok;
break;
default: state = CAN_TxStatus_Failed;
break;
}
return (uint8_t) state;
}
/**
* @brief Cancels a transmit request.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param Mailbox: Mailbox number.
* @retval None.
*/
void CAN_CancelTransmit(CAN_TypeDef* CANx, uint8_t Mailbox)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_TRANSMITMAILBOX(Mailbox));
/* abort transmission */
switch (Mailbox)
{
case (CAN_TXMAILBOX_0): CANx->TSR |= CAN_TSR_ABRQ0;
break;
case (CAN_TXMAILBOX_1): CANx->TSR |= CAN_TSR_ABRQ1;
break;
case (CAN_TXMAILBOX_2): CANx->TSR |= CAN_TSR_ABRQ2;
break;
default:
break;
}
}
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/**
* @brief Receives a message.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1.
* @param RxMessage: pointer to a structure receive message which contains
* CAN Id, CAN DLC, CAN datas and FMI number.
* @retval None.
*/
void CAN_Receive(CAN_TypeDef* CANx, uint8_t FIFONumber, CanRxMsg* RxMessage)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_FIFO(FIFONumber));
/* Get the Id */
RxMessage->IDE = (uint8_t)0x04 & CANx->sFIFOMailBox[FIFONumber].RIR;
if (RxMessage->IDE == CAN_Id_Standard)
{
RxMessage->StdId = (uint32_t)0x000007FF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 21);
}
else
{
RxMessage->ExtId = (uint32_t)0x1FFFFFFF & (CANx->sFIFOMailBox[FIFONumber].RIR >> 3);
}
RxMessage->RTR = (uint8_t)0x02 & CANx->sFIFOMailBox[FIFONumber].RIR;
/* Get the DLC */
RxMessage->DLC = (uint8_t)0x0F & CANx->sFIFOMailBox[FIFONumber].RDTR;
/* Get the FMI */
RxMessage->FMI = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDTR >> 8);
/* Get the data field */
RxMessage->Data[0] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDLR;
RxMessage->Data[1] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 8);
RxMessage->Data[2] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 16);
RxMessage->Data[3] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDLR >> 24);
RxMessage->Data[4] = (uint8_t)0xFF & CANx->sFIFOMailBox[FIFONumber].RDHR;
RxMessage->Data[5] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 8);
RxMessage->Data[6] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 16);
RxMessage->Data[7] = (uint8_t)0xFF & (CANx->sFIFOMailBox[FIFONumber].RDHR >> 24);
/* Release the FIFO */
/* Release FIFO0 */
if (FIFONumber == CAN_FIFO0)
{
CANx->RF0R |= CAN_RF0R_RFOM0;
}
/* Release FIFO1 */
else /* FIFONumber == CAN_FIFO1 */
{
CANx->RF1R |= CAN_RF1R_RFOM1;
}
}
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/**
* @brief Releases the specified FIFO.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param FIFONumber: FIFO to release, CAN_FIFO0 or CAN_FIFO1.
* @retval None.
*/
void CAN_FIFORelease(CAN_TypeDef* CANx, uint8_t FIFONumber)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_FIFO(FIFONumber));
/* Release FIFO0 */
if (FIFONumber == CAN_FIFO0)
{
CANx->RF0R |= CAN_RF0R_RFOM0;
}
/* Release FIFO1 */
else /* FIFONumber == CAN_FIFO1 */
{
CANx->RF1R |= CAN_RF1R_RFOM1;
}
}
/**
* @brief Returns the number of pending messages.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param FIFONumber: Receive FIFO number, CAN_FIFO0 or CAN_FIFO1.
* @retval NbMessage : which is the number of pending message.
*/
uint8_t CAN_MessagePending(CAN_TypeDef* CANx, uint8_t FIFONumber)
{
uint8_t message_pending=0;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_FIFO(FIFONumber));
if (FIFONumber == CAN_FIFO0)
{
message_pending = (uint8_t)(CANx->RF0R&(uint32_t)0x03);
}
else if (FIFONumber == CAN_FIFO1)
{
message_pending = (uint8_t)(CANx->RF1R&(uint32_t)0x03);
}
else
{
message_pending = 0;
}
return message_pending;
}
/**
* @brief Select the CAN Operation mode.
* @param CAN_OperatingMode : CAN Operating Mode. This parameter can be one
* of @ref CAN_OperatingMode_TypeDef enumeration.
* @retval status of the requested mode which can be
* - CAN_ModeStatus_Failed CAN failed entering the specific mode
* - CAN_ModeStatus_Success CAN Succeed entering the specific mode
*/
uint8_t CAN_OperatingModeRequest(CAN_TypeDef* CANx, uint8_t CAN_OperatingMode)
{
uint8_t status = CAN_ModeStatus_Failed;
/* Timeout for INAK or also for SLAK bits*/
uint32_t timeout = INAK_TIMEOUT;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_OPERATING_MODE(CAN_OperatingMode));
if (CAN_OperatingMode == CAN_OperatingMode_Initialization)
{
/* Request initialisation */
CANx->MCR = (uint32_t)((CANx->MCR & (uint32_t)(~(uint32_t)CAN_MCR_SLEEP)) | CAN_MCR_INRQ);
/* Wait the acknowledge */
while (((CANx->MSR & CAN_MODE_MASK) != CAN_MSR_INAK) && (timeout != 0))
{
timeout--;
}
if ((CANx->MSR & CAN_MODE_MASK) != CAN_MSR_INAK)
{
status = CAN_ModeStatus_Failed;
}
else
{
status = CAN_ModeStatus_Success;
}
}
else if (CAN_OperatingMode == CAN_OperatingMode_Normal)
{
/* Request leave initialisation and sleep mode and enter Normal mode */
CANx->MCR &= (uint32_t)(~(CAN_MCR_SLEEP|CAN_MCR_INRQ));
/* Wait the acknowledge */
while (((CANx->MSR & CAN_MODE_MASK) != 0) && (timeout!=0))
{
timeout--;
}
if ((CANx->MSR & CAN_MODE_MASK) != 0)
{
status = CAN_ModeStatus_Failed;
}
else
{
status = CAN_ModeStatus_Success;
}
}
else if (CAN_OperatingMode == CAN_OperatingMode_Sleep)
{
/* Request Sleep mode */
CANx->MCR = (uint32_t)((CANx->MCR & (uint32_t)(~(uint32_t)CAN_MCR_INRQ)) | CAN_MCR_SLEEP);
/* Wait the acknowledge */
while (((CANx->MSR & CAN_MODE_MASK) != CAN_MSR_SLAK) && (timeout!=0))
{
timeout--;
}
if ((CANx->MSR & CAN_MODE_MASK) != CAN_MSR_SLAK)
{
status = CAN_ModeStatus_Failed;
}
else
{
status = CAN_ModeStatus_Success;
}
}
else
{
status = CAN_ModeStatus_Failed;
}
return (uint8_t) status;
}
/**
* @brief Enters the low power mode.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @retval status: CAN_Sleep_Ok if sleep entered, CAN_Sleep_Failed in an
* other case.
*/
uint8_t CAN_Sleep(CAN_TypeDef* CANx)
{
uint8_t sleepstatus = CAN_Sleep_Failed;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
/* Request Sleep mode */
CANx->MCR = (((CANx->MCR) & (uint32_t)(~(uint32_t)CAN_MCR_INRQ)) | CAN_MCR_SLEEP);
/* Sleep mode status */
if ((CANx->MSR & (CAN_MSR_SLAK|CAN_MSR_INAK)) == CAN_MSR_SLAK)
{
/* Sleep mode not entered */
sleepstatus = CAN_Sleep_Ok;
}
/* return sleep mode status */
return (uint8_t)sleepstatus;
}
/**
* @brief Wakes the CAN up.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @retval status: CAN_WakeUp_Ok if sleep mode left, CAN_WakeUp_Failed in an
* other case.
*/
uint8_t CAN_WakeUp(CAN_TypeDef* CANx)
{
uint32_t wait_slak = SLAK_TIMEOUT;
uint8_t wakeupstatus = CAN_WakeUp_Failed;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
/* Wake up request */
CANx->MCR &= ~(uint32_t)CAN_MCR_SLEEP;
/* Sleep mode status */
while(((CANx->MSR & CAN_MSR_SLAK) == CAN_MSR_SLAK)&&(wait_slak!=0x00))
{
wait_slak--;
}
if((CANx->MSR & CAN_MSR_SLAK) != CAN_MSR_SLAK)
{
/* wake up done : Sleep mode exited */
wakeupstatus = CAN_WakeUp_Ok;
}
/* return wakeup status */
return (uint8_t)wakeupstatus;
}
/**
* @brief Returns the CANx's last error code (LEC).
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @retval CAN_ErrorCode: specifies the Error code :
* - CAN_ERRORCODE_NoErr No Error
* - CAN_ERRORCODE_StuffErr Stuff Error
* - CAN_ERRORCODE_FormErr Form Error
* - CAN_ERRORCODE_ACKErr Acknowledgment Error
* - CAN_ERRORCODE_BitRecessiveErr Bit Recessive Error
* - CAN_ERRORCODE_BitDominantErr Bit Dominant Error
* - CAN_ERRORCODE_CRCErr CRC Error
* - CAN_ERRORCODE_SoftwareSetErr Software Set Error
*/
uint8_t CAN_GetLastErrorCode(CAN_TypeDef* CANx)
{
uint8_t errorcode=0;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
/* Get the error code*/
errorcode = (((uint8_t)CANx->ESR) & (uint8_t)CAN_ESR_LEC);
/* Return the error code*/
return errorcode;
}
/**
* @brief Returns the CANx Receive Error Counter (REC).
* @note In case of an error during reception, this counter is incremented
* by 1 or by 8 depending on the error condition as defined by the CAN
* standard. After every successful reception, the counter is
* decremented by 1 or reset to 120 if its value was higher than 128.
* When the counter value exceeds 127, the CAN controller enters the
* error passive state.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @retval CAN Receive Error Counter.
*/
uint8_t CAN_GetReceiveErrorCounter(CAN_TypeDef* CANx)
{
uint8_t counter=0;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
/* Get the Receive Error Counter*/
counter = (uint8_t)((CANx->ESR & CAN_ESR_REC)>> 24);
/* Return the Receive Error Counter*/
return counter;
}
/**
* @brief Returns the LSB of the 9-bit CANx Transmit Error Counter(TEC).
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @retval LSB of the 9-bit CAN Transmit Error Counter.
*/
uint8_t CAN_GetLSBTransmitErrorCounter(CAN_TypeDef* CANx)
{
uint8_t counter=0;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
/* Get the LSB of the 9-bit CANx Transmit Error Counter(TEC) */
counter = (uint8_t)((CANx->ESR & CAN_ESR_TEC)>> 16);
/* Return the LSB of the 9-bit CANx Transmit Error Counter(TEC) */
return counter;
}
/**
* @brief Enables or disables the specified CANx interrupts.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param CAN_IT: specifies the CAN interrupt sources to be enabled or disabled.
* This parameter can be:
* - CAN_IT_TME,
* - CAN_IT_FMP0,
* - CAN_IT_FF0,
* - CAN_IT_FOV0,
* - CAN_IT_FMP1,
* - CAN_IT_FF1,
* - CAN_IT_FOV1,
* - CAN_IT_EWG,
* - CAN_IT_EPV,
* - CAN_IT_LEC,
* - CAN_IT_ERR,
* - CAN_IT_WKU or
* - CAN_IT_SLK.
* @param NewState: new state of the CAN interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None.
*/
void CAN_ITConfig(CAN_TypeDef* CANx, uint32_t CAN_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_IT(CAN_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected CANx interrupt */
CANx->IER |= CAN_IT;
}
else
{
/* Disable the selected CANx interrupt */
CANx->IER &= ~CAN_IT;
}
}
/**
* @brief Checks whether the specified CAN flag is set or not.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param CAN_FLAG: specifies the flag to check.
* This parameter can be one of the following flags:
* - CAN_FLAG_EWG
* - CAN_FLAG_EPV
* - CAN_FLAG_BOF
* - CAN_FLAG_RQCP0
* - CAN_FLAG_RQCP1
* - CAN_FLAG_RQCP2
* - CAN_FLAG_FMP1
* - CAN_FLAG_FF1
* - CAN_FLAG_FOV1
* - CAN_FLAG_FMP0
* - CAN_FLAG_FF0
* - CAN_FLAG_FOV0
* - CAN_FLAG_WKU
* - CAN_FLAG_SLAK
* - CAN_FLAG_LEC
* @retval The new state of CAN_FLAG (SET or RESET).
*/
FlagStatus CAN_GetFlagStatus(CAN_TypeDef* CANx, uint32_t CAN_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_GET_FLAG(CAN_FLAG));
if((CAN_FLAG & CAN_FLAGS_ESR) != (uint32_t)RESET)
{
/* Check the status of the specified CAN flag */
if ((CANx->ESR & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET)
{
/* CAN_FLAG is set */
bitstatus = SET;
}
else
{
/* CAN_FLAG is reset */
bitstatus = RESET;
}
}
else if((CAN_FLAG & CAN_FLAGS_MSR) != (uint32_t)RESET)
{
/* Check the status of the specified CAN flag */
if ((CANx->MSR & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET)
{
/* CAN_FLAG is set */
bitstatus = SET;
}
else
{
/* CAN_FLAG is reset */
bitstatus = RESET;
}
}
else if((CAN_FLAG & CAN_FLAGS_TSR) != (uint32_t)RESET)
{
/* Check the status of the specified CAN flag */
if ((CANx->TSR & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET)
{
/* CAN_FLAG is set */
bitstatus = SET;
}
else
{
/* CAN_FLAG is reset */
bitstatus = RESET;
}
}
else if((CAN_FLAG & CAN_FLAGS_RF0R) != (uint32_t)RESET)
{
/* Check the status of the specified CAN flag */
if ((CANx->RF0R & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET)
{
/* CAN_FLAG is set */
bitstatus = SET;
}
else
{
/* CAN_FLAG is reset */
bitstatus = RESET;
}
}
else /* If(CAN_FLAG & CAN_FLAGS_RF1R != (uint32_t)RESET) */
{
/* Check the status of the specified CAN flag */
if ((uint32_t)(CANx->RF1R & (CAN_FLAG & 0x000FFFFF)) != (uint32_t)RESET)
{
/* CAN_FLAG is set */
bitstatus = SET;
}
else
{
/* CAN_FLAG is reset */
bitstatus = RESET;
}
}
/* Return the CAN_FLAG status */
return bitstatus;
}
/**
* @brief Clears the CAN's pending flags.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param CAN_FLAG: specifies the flag to clear.
* This parameter can be one of the following flags:
* - CAN_FLAG_RQCP0
* - CAN_FLAG_RQCP1
* - CAN_FLAG_RQCP2
* - CAN_FLAG_FF1
* - CAN_FLAG_FOV1
* - CAN_FLAG_FF0
* - CAN_FLAG_FOV0
* - CAN_FLAG_WKU
* - CAN_FLAG_SLAK
* - CAN_FLAG_LEC
* @retval None.
*/
void CAN_ClearFlag(CAN_TypeDef* CANx, uint32_t CAN_FLAG)
{
uint32_t flagtmp=0;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_CLEAR_FLAG(CAN_FLAG));
if (CAN_FLAG == CAN_FLAG_LEC) /* ESR register */
{
/* Clear the selected CAN flags */
CANx->ESR = (uint32_t)RESET;
}
else /* MSR or TSR or RF0R or RF1R */
{
flagtmp = CAN_FLAG & 0x000FFFFF;
if ((CAN_FLAG & CAN_FLAGS_RF0R)!=(uint32_t)RESET)
{
/* Receive Flags */
CANx->RF0R = (uint32_t)(flagtmp);
}
else if ((CAN_FLAG & CAN_FLAGS_RF1R)!=(uint32_t)RESET)
{
/* Receive Flags */
CANx->RF1R = (uint32_t)(flagtmp);
}
else if ((CAN_FLAG & CAN_FLAGS_TSR)!=(uint32_t)RESET)
{
/* Transmit Flags */
CANx->TSR = (uint32_t)(flagtmp);
}
else /* If((CAN_FLAG & CAN_FLAGS_MSR)!=(uint32_t)RESET) */
{
/* Operating mode Flags */
CANx->MSR = (uint32_t)(flagtmp);
}
}
}
/**
* @brief Checks whether the specified CANx interrupt has occurred or not.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param CAN_IT: specifies the CAN interrupt source to check.
* This parameter can be one of the following flags:
* - CAN_IT_TME
* - CAN_IT_FMP0
* - CAN_IT_FF0
* - CAN_IT_FOV0
* - CAN_IT_FMP1
* - CAN_IT_FF1
* - CAN_IT_FOV1
* - CAN_IT_WKU
* - CAN_IT_SLK
* - CAN_IT_EWG
* - CAN_IT_EPV
* - CAN_IT_BOF
* - CAN_IT_LEC
* - CAN_IT_ERR
* @retval The current state of CAN_IT (SET or RESET).
*/
ITStatus CAN_GetITStatus(CAN_TypeDef* CANx, uint32_t CAN_IT)
{
ITStatus itstatus = RESET;
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_IT(CAN_IT));
/* check the enable interrupt bit */
if((CANx->IER & CAN_IT) != RESET)
{
/* in case the Interrupt is enabled, .... */
switch (CAN_IT)
{
case CAN_IT_TME:
/* Check CAN_TSR_RQCPx bits */
itstatus = CheckITStatus(CANx->TSR, CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2);
break;
case CAN_IT_FMP0:
/* Check CAN_RF0R_FMP0 bit */
itstatus = CheckITStatus(CANx->RF0R, CAN_RF0R_FMP0);
break;
case CAN_IT_FF0:
/* Check CAN_RF0R_FULL0 bit */
itstatus = CheckITStatus(CANx->RF0R, CAN_RF0R_FULL0);
break;
case CAN_IT_FOV0:
/* Check CAN_RF0R_FOVR0 bit */
itstatus = CheckITStatus(CANx->RF0R, CAN_RF0R_FOVR0);
break;
case CAN_IT_FMP1:
/* Check CAN_RF1R_FMP1 bit */
itstatus = CheckITStatus(CANx->RF1R, CAN_RF1R_FMP1);
break;
case CAN_IT_FF1:
/* Check CAN_RF1R_FULL1 bit */
itstatus = CheckITStatus(CANx->RF1R, CAN_RF1R_FULL1);
break;
case CAN_IT_FOV1:
/* Check CAN_RF1R_FOVR1 bit */
itstatus = CheckITStatus(CANx->RF1R, CAN_RF1R_FOVR1);
break;
case CAN_IT_WKU:
/* Check CAN_MSR_WKUI bit */
itstatus = CheckITStatus(CANx->MSR, CAN_MSR_WKUI);
break;
case CAN_IT_SLK:
/* Check CAN_MSR_SLAKI bit */
itstatus = CheckITStatus(CANx->MSR, CAN_MSR_SLAKI);
break;
case CAN_IT_EWG:
/* Check CAN_ESR_EWGF bit */
itstatus = CheckITStatus(CANx->ESR, CAN_ESR_EWGF);
break;
case CAN_IT_EPV:
/* Check CAN_ESR_EPVF bit */
itstatus = CheckITStatus(CANx->ESR, CAN_ESR_EPVF);
break;
case CAN_IT_BOF:
/* Check CAN_ESR_BOFF bit */
itstatus = CheckITStatus(CANx->ESR, CAN_ESR_BOFF);
break;
case CAN_IT_LEC:
/* Check CAN_ESR_LEC bit */
itstatus = CheckITStatus(CANx->ESR, CAN_ESR_LEC);
break;
case CAN_IT_ERR:
/* Check CAN_MSR_ERRI bit */
itstatus = CheckITStatus(CANx->MSR, CAN_MSR_ERRI);
break;
default :
/* in case of error, return RESET */
itstatus = RESET;
break;
}
}
else
{
/* in case the Interrupt is not enabled, return RESET */
itstatus = RESET;
}
/* Return the CAN_IT status */
return itstatus;
}
/**
* @brief Clears the CANx's interrupt pending bits.
* @param CANx: where x can be 1 or 2 to to select the CAN peripheral.
* @param CAN_IT: specifies the interrupt pending bit to clear.
* - CAN_IT_TME
* - CAN_IT_FF0
* - CAN_IT_FOV0
* - CAN_IT_FF1
* - CAN_IT_FOV1
* - CAN_IT_WKU
* - CAN_IT_SLK
* - CAN_IT_EWG
* - CAN_IT_EPV
* - CAN_IT_BOF
* - CAN_IT_LEC
* - CAN_IT_ERR
* @retval None.
*/
void CAN_ClearITPendingBit(CAN_TypeDef* CANx, uint32_t CAN_IT)
{
/* Check the parameters */
assert_param(IS_CAN_ALL_PERIPH(CANx));
assert_param(IS_CAN_CLEAR_IT(CAN_IT));
switch (CAN_IT)
{
case CAN_IT_TME:
/* Clear CAN_TSR_RQCPx (rc_w1)*/
CANx->TSR = CAN_TSR_RQCP0|CAN_TSR_RQCP1|CAN_TSR_RQCP2;
break;
case CAN_IT_FF0:
/* Clear CAN_RF0R_FULL0 (rc_w1)*/
CANx->RF0R = CAN_RF0R_FULL0;
break;
case CAN_IT_FOV0:
/* Clear CAN_RF0R_FOVR0 (rc_w1)*/
CANx->RF0R = CAN_RF0R_FOVR0;
break;
case CAN_IT_FF1:
/* Clear CAN_RF1R_FULL1 (rc_w1)*/
CANx->RF1R = CAN_RF1R_FULL1;
break;
case CAN_IT_FOV1:
/* Clear CAN_RF1R_FOVR1 (rc_w1)*/
CANx->RF1R = CAN_RF1R_FOVR1;
break;
case CAN_IT_WKU:
/* Clear CAN_MSR_WKUI (rc_w1)*/
CANx->MSR = CAN_MSR_WKUI;
break;
case CAN_IT_SLK:
/* Clear CAN_MSR_SLAKI (rc_w1)*/
CANx->MSR = CAN_MSR_SLAKI;
break;
case CAN_IT_EWG:
/* Clear CAN_MSR_ERRI (rc_w1) */
CANx->MSR = CAN_MSR_ERRI;
/* Note : the corresponding Flag is cleared by hardware depending
of the CAN Bus status*/
break;
case CAN_IT_EPV:
/* Clear CAN_MSR_ERRI (rc_w1) */
CANx->MSR = CAN_MSR_ERRI;
/* Note : the corresponding Flag is cleared by hardware depending
of the CAN Bus status*/
break;
case CAN_IT_BOF:
/* Clear CAN_MSR_ERRI (rc_w1) */
CANx->MSR = CAN_MSR_ERRI;
/* Note : the corresponding Flag is cleared by hardware depending
of the CAN Bus status*/
break;
case CAN_IT_LEC:
/* Clear LEC bits */
CANx->ESR = RESET;
/* Clear CAN_MSR_ERRI (rc_w1) */
CANx->MSR = CAN_MSR_ERRI;
break;
case CAN_IT_ERR:
/*Clear LEC bits */
CANx->ESR = RESET;
/* Clear CAN_MSR_ERRI (rc_w1) */
CANx->MSR = CAN_MSR_ERRI;
/* Note : BOFF, EPVF and EWGF Flags are cleared by hardware depending
of the CAN Bus status*/
break;
default :
break;
}
}
/**
* @brief Checks whether the CAN interrupt has occurred or not.
* @param CAN_Reg: specifies the CAN interrupt register to check.
* @param It_Bit: specifies the interrupt source bit to check.
* @retval The new state of the CAN Interrupt (SET or RESET).
*/
static ITStatus CheckITStatus(uint32_t CAN_Reg, uint32_t It_Bit)
{
ITStatus pendingbitstatus = RESET;
if ((CAN_Reg & It_Bit) != (uint32_t)RESET)
{
/* CAN_IT is set */
pendingbitstatus = SET;
}
else
{
/* CAN_IT is reset */
pendingbitstatus = RESET;
}
return pendingbitstatus;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_cec.c
================================================
/**
******************************************************************************
* @file stm32f10x_cec.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the CEC firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_cec.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup CEC
* @brief CEC driver modules
* @{
*/
/** @defgroup CEC_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup CEC_Private_Defines
* @{
*/
/* ------------ CEC registers bit address in the alias region ----------- */
#define CEC_OFFSET (CEC_BASE - PERIPH_BASE)
/* --- CFGR Register ---*/
/* Alias word address of PE bit */
#define CFGR_OFFSET (CEC_OFFSET + 0x00)
#define PE_BitNumber 0x00
#define CFGR_PE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (PE_BitNumber * 4))
/* Alias word address of IE bit */
#define IE_BitNumber 0x01
#define CFGR_IE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (IE_BitNumber * 4))
/* --- CSR Register ---*/
/* Alias word address of TSOM bit */
#define CSR_OFFSET (CEC_OFFSET + 0x10)
#define TSOM_BitNumber 0x00
#define CSR_TSOM_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TSOM_BitNumber * 4))
/* Alias word address of TEOM bit */
#define TEOM_BitNumber 0x01
#define CSR_TEOM_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (TEOM_BitNumber * 4))
#define CFGR_CLEAR_Mask (uint8_t)(0xF3) /* CFGR register Mask */
#define FLAG_Mask ((uint32_t)0x00FFFFFF) /* CEC FLAG mask */
/**
* @}
*/
/** @defgroup CEC_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup CEC_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup CEC_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup CEC_Private_Functions
* @{
*/
/**
* @brief Deinitializes the CEC peripheral registers to their default reset
* values.
* @param None
* @retval None
*/
void CEC_DeInit(void)
{
/* Enable CEC reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CEC, ENABLE);
/* Release CEC from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_CEC, DISABLE);
}
/**
* @brief Initializes the CEC peripheral according to the specified
* parameters in the CEC_InitStruct.
* @param CEC_InitStruct: pointer to an CEC_InitTypeDef structure that
* contains the configuration information for the specified
* CEC peripheral.
* @retval None
*/
void CEC_Init(CEC_InitTypeDef* CEC_InitStruct)
{
// [ILG] uint16_t tmpreg = 0;
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_CEC_BIT_TIMING_ERROR_MODE(CEC_InitStruct->CEC_BitTimingMode));
assert_param(IS_CEC_BIT_PERIOD_ERROR_MODE(CEC_InitStruct->CEC_BitPeriodMode));
/*---------------------------- CEC CFGR Configuration -----------------*/
/* Get the CEC CFGR value */
tmpreg = CEC->CFGR;
/* Clear BTEM and BPEM bits */
tmpreg &= CFGR_CLEAR_Mask;
/* Configure CEC: Bit Timing Error and Bit Period Error */
tmpreg |= (uint16_t)(CEC_InitStruct->CEC_BitTimingMode | CEC_InitStruct->CEC_BitPeriodMode);
/* Write to CEC CFGR register*/
CEC->CFGR = tmpreg;
}
/**
* @brief Enables or disables the specified CEC peripheral.
* @param NewState: new state of the CEC peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void CEC_Cmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CFGR_PE_BB = (uint32_t)NewState;
if(NewState == DISABLE)
{
/* Wait until the PE bit is cleared by hardware (Idle Line detected) */
while((CEC->CFGR & CEC_CFGR_PE) != (uint32_t)RESET)
{
}
}
}
/**
* @brief Enables or disables the CEC interrupt.
* @param NewState: new state of the CEC interrupt.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void CEC_ITConfig(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CFGR_IE_BB = (uint32_t)NewState;
}
/**
* @brief Defines the Own Address of the CEC device.
* @param CEC_OwnAddress: The CEC own address
* @retval None
*/
void CEC_OwnAddressConfig(uint8_t CEC_OwnAddress)
{
/* Check the parameters */
assert_param(IS_CEC_ADDRESS(CEC_OwnAddress));
/* Set the CEC own address */
CEC->OAR = CEC_OwnAddress;
}
/**
* @brief Sets the CEC prescaler value.
* @param CEC_Prescaler: CEC prescaler new value
* @retval None
*/
void CEC_SetPrescaler(uint16_t CEC_Prescaler)
{
/* Check the parameters */
assert_param(IS_CEC_PRESCALER(CEC_Prescaler));
/* Set the Prescaler value*/
CEC->PRES = CEC_Prescaler;
}
/**
* @brief Transmits single data through the CEC peripheral.
* @param Data: the data to transmit.
* @retval None
*/
void CEC_SendDataByte(uint8_t Data)
{
/* Transmit Data */
CEC->TXD = Data ;
}
/**
* @brief Returns the most recent received data by the CEC peripheral.
* @param None
* @retval The received data.
*/
uint8_t CEC_ReceiveDataByte(void)
{
/* Receive Data */
return (uint8_t)(CEC->RXD);
}
/**
* @brief Starts a new message.
* @param None
* @retval None
*/
void CEC_StartOfMessage(void)
{
/* Starts of new message */
*(__IO uint32_t *) CSR_TSOM_BB = (uint32_t)0x1;
}
/**
* @brief Transmits message with or without an EOM bit.
* @param NewState: new state of the CEC Tx End Of Message.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void CEC_EndOfMessageCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
/* The data byte will be transmitted with or without an EOM bit*/
*(__IO uint32_t *) CSR_TEOM_BB = (uint32_t)NewState;
}
/**
* @brief Gets the CEC flag status
* @param CEC_FLAG: specifies the CEC flag to check.
* This parameter can be one of the following values:
* @arg CEC_FLAG_BTE: Bit Timing Error
* @arg CEC_FLAG_BPE: Bit Period Error
* @arg CEC_FLAG_RBTFE: Rx Block Transfer Finished Error
* @arg CEC_FLAG_SBE: Start Bit Error
* @arg CEC_FLAG_ACKE: Block Acknowledge Error
* @arg CEC_FLAG_LINE: Line Error
* @arg CEC_FLAG_TBTFE: Tx Block Transfer Finished Error
* @arg CEC_FLAG_TEOM: Tx End Of Message
* @arg CEC_FLAG_TERR: Tx Error
* @arg CEC_FLAG_TBTRF: Tx Byte Transfer Request or Block Transfer Finished
* @arg CEC_FLAG_RSOM: Rx Start Of Message
* @arg CEC_FLAG_REOM: Rx End Of Message
* @arg CEC_FLAG_RERR: Rx Error
* @arg CEC_FLAG_RBTF: Rx Byte/Block Transfer Finished
* @retval The new state of CEC_FLAG (SET or RESET)
*/
FlagStatus CEC_GetFlagStatus(uint32_t CEC_FLAG)
{
FlagStatus bitstatus = RESET;
uint32_t cecreg = 0, cecbase = 0;
/* Check the parameters */
assert_param(IS_CEC_GET_FLAG(CEC_FLAG));
/* Get the CEC peripheral base address */
cecbase = (uint32_t)(CEC_BASE);
/* Read flag register index */
cecreg = CEC_FLAG >> 28;
/* Get bit[23:0] of the flag */
CEC_FLAG &= FLAG_Mask;
if(cecreg != 0)
{
/* Flag in CEC ESR Register */
CEC_FLAG = (uint32_t)(CEC_FLAG >> 16);
/* Get the CEC ESR register address */
cecbase += 0xC;
}
else
{
/* Get the CEC CSR register address */
cecbase += 0x10;
}
if(((*(__IO uint32_t *)cecbase) & CEC_FLAG) != (uint32_t)RESET)
{
/* CEC_FLAG is set */
bitstatus = SET;
}
else
{
/* CEC_FLAG is reset */
bitstatus = RESET;
}
/* Return the CEC_FLAG status */
return bitstatus;
}
/**
* @brief Clears the CEC's pending flags.
* @param CEC_FLAG: specifies the flag to clear.
* This parameter can be any combination of the following values:
* @arg CEC_FLAG_TERR: Tx Error
* @arg CEC_FLAG_TBTRF: Tx Byte Transfer Request or Block Transfer Finished
* @arg CEC_FLAG_RSOM: Rx Start Of Message
* @arg CEC_FLAG_REOM: Rx End Of Message
* @arg CEC_FLAG_RERR: Rx Error
* @arg CEC_FLAG_RBTF: Rx Byte/Block Transfer Finished
* @retval None
*/
void CEC_ClearFlag(uint32_t CEC_FLAG)
{
uint32_t tmp = 0x0;
/* Check the parameters */
assert_param(IS_CEC_CLEAR_FLAG(CEC_FLAG));
tmp = CEC->CSR & 0x2;
/* Clear the selected CEC flags */
CEC->CSR &= (uint32_t)(((~(uint32_t)CEC_FLAG) & 0xFFFFFFFC) | tmp);
}
/**
* @brief Checks whether the specified CEC interrupt has occurred or not.
* @param CEC_IT: specifies the CEC interrupt source to check.
* This parameter can be one of the following values:
* @arg CEC_IT_TERR: Tx Error
* @arg CEC_IT_TBTF: Tx Block Transfer Finished
* @arg CEC_IT_RERR: Rx Error
* @arg CEC_IT_RBTF: Rx Block Transfer Finished
* @retval The new state of CEC_IT (SET or RESET).
*/
ITStatus CEC_GetITStatus(uint8_t CEC_IT)
{
ITStatus bitstatus = RESET;
uint32_t enablestatus = 0;
/* Check the parameters */
assert_param(IS_CEC_GET_IT(CEC_IT));
/* Get the CEC IT enable bit status */
enablestatus = (CEC->CFGR & (uint8_t)CEC_CFGR_IE) ;
/* Check the status of the specified CEC interrupt */
if (((CEC->CSR & CEC_IT) != (uint32_t)RESET) && enablestatus)
{
/* CEC_IT is set */
bitstatus = SET;
}
else
{
/* CEC_IT is reset */
bitstatus = RESET;
}
/* Return the CEC_IT status */
return bitstatus;
}
/**
* @brief Clears the CEC's interrupt pending bits.
* @param CEC_IT: specifies the CEC interrupt pending bit to clear.
* This parameter can be any combination of the following values:
* @arg CEC_IT_TERR: Tx Error
* @arg CEC_IT_TBTF: Tx Block Transfer Finished
* @arg CEC_IT_RERR: Rx Error
* @arg CEC_IT_RBTF: Rx Block Transfer Finished
* @retval None
*/
void CEC_ClearITPendingBit(uint16_t CEC_IT)
{
uint32_t tmp = 0x0;
/* Check the parameters */
assert_param(IS_CEC_GET_IT(CEC_IT));
tmp = CEC->CSR & 0x2;
/* Clear the selected CEC interrupt pending bits */
CEC->CSR &= (uint32_t)(((~(uint32_t)CEC_IT) & 0xFFFFFFFC) | tmp);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_crc.c
================================================
/**
******************************************************************************
* @file stm32f10x_crc.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the CRC firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_crc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup CRC
* @brief CRC driver modules
* @{
*/
/** @defgroup CRC_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup CRC_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup CRC_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup CRC_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup CRC_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup CRC_Private_Functions
* @{
*/
/**
* @brief Resets the CRC Data register (DR).
* @param None
* @retval None
*/
void CRC_ResetDR(void)
{
/* Reset CRC generator */
CRC->CR = CRC_CR_RESET;
}
/**
* @brief Computes the 32-bit CRC of a given data word(32-bit).
* @param Data: data word(32-bit) to compute its CRC
* @retval 32-bit CRC
*/
uint32_t CRC_CalcCRC(uint32_t Data)
{
CRC->DR = Data;
return (CRC->DR);
}
/**
* @brief Computes the 32-bit CRC of a given buffer of data word(32-bit).
* @param pBuffer: pointer to the buffer containing the data to be computed
* @param BufferLength: length of the buffer to be computed
* @retval 32-bit CRC
*/
uint32_t CRC_CalcBlockCRC(uint32_t pBuffer[], uint32_t BufferLength)
{
uint32_t index = 0;
for(index = 0; index < BufferLength; index++)
{
CRC->DR = pBuffer[index];
}
return (CRC->DR);
}
/**
* @brief Returns the current CRC value.
* @param None
* @retval 32-bit CRC
*/
uint32_t CRC_GetCRC(void)
{
return (CRC->DR);
}
/**
* @brief Stores a 8-bit data in the Independent Data(ID) register.
* @param IDValue: 8-bit value to be stored in the ID register
* @retval None
*/
void CRC_SetIDRegister(uint8_t IDValue)
{
CRC->IDR = IDValue;
}
/**
* @brief Returns the 8-bit data stored in the Independent Data(ID) register
* @param None
* @retval 8-bit value of the ID register
*/
uint8_t CRC_GetIDRegister(void)
{
return (CRC->IDR);
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_dac.c
================================================
/**
******************************************************************************
* @file stm32f10x_dac.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the DAC firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_dac.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup DAC
* @brief DAC driver modules
* @{
*/
/** @defgroup DAC_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup DAC_Private_Defines
* @{
*/
/* CR register Mask */
#define CR_CLEAR_MASK ((uint32_t)0x00000FFE)
/* DAC Dual Channels SWTRIG masks */
#define DUAL_SWTRIG_SET ((uint32_t)0x00000003)
#define DUAL_SWTRIG_RESET ((uint32_t)0xFFFFFFFC)
/* DHR registers offsets */
#define DHR12R1_OFFSET ((uint32_t)0x00000008)
#define DHR12R2_OFFSET ((uint32_t)0x00000014)
#define DHR12RD_OFFSET ((uint32_t)0x00000020)
/* DOR register offset */
#define DOR_OFFSET ((uint32_t)0x0000002C)
/**
* @}
*/
/** @defgroup DAC_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup DAC_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup DAC_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup DAC_Private_Functions
* @{
*/
/**
* @brief Deinitializes the DAC peripheral registers to their default reset values.
* @param None
* @retval None
*/
void DAC_DeInit(void)
{
/* Enable DAC reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, ENABLE);
/* Release DAC from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_DAC, DISABLE);
}
/**
* @brief Initializes the DAC peripheral according to the specified
* parameters in the DAC_InitStruct.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param DAC_InitStruct: pointer to a DAC_InitTypeDef structure that
* contains the configuration information for the specified DAC channel.
* @retval None
*/
void DAC_Init(uint32_t DAC_Channel, DAC_InitTypeDef* DAC_InitStruct)
{
uint32_t tmpreg1 = 0, tmpreg2 = 0;
/* Check the DAC parameters */
assert_param(IS_DAC_TRIGGER(DAC_InitStruct->DAC_Trigger));
assert_param(IS_DAC_GENERATE_WAVE(DAC_InitStruct->DAC_WaveGeneration));
assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude));
assert_param(IS_DAC_OUTPUT_BUFFER_STATE(DAC_InitStruct->DAC_OutputBuffer));
/*---------------------------- DAC CR Configuration --------------------------*/
/* Get the DAC CR value */
tmpreg1 = DAC->CR;
/* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */
tmpreg1 &= ~(CR_CLEAR_MASK << DAC_Channel);
/* Configure for the selected DAC channel: buffer output, trigger, wave generation,
mask/amplitude for wave generation */
/* Set TSELx and TENx bits according to DAC_Trigger value */
/* Set WAVEx bits according to DAC_WaveGeneration value */
/* Set MAMPx bits according to DAC_LFSRUnmask_TriangleAmplitude value */
/* Set BOFFx bit according to DAC_OutputBuffer value */
tmpreg2 = (DAC_InitStruct->DAC_Trigger | DAC_InitStruct->DAC_WaveGeneration |
DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude | DAC_InitStruct->DAC_OutputBuffer);
/* Calculate CR register value depending on DAC_Channel */
tmpreg1 |= tmpreg2 << DAC_Channel;
/* Write to DAC CR */
DAC->CR = tmpreg1;
}
/**
* @brief Fills each DAC_InitStruct member with its default value.
* @param DAC_InitStruct : pointer to a DAC_InitTypeDef structure which will
* be initialized.
* @retval None
*/
void DAC_StructInit(DAC_InitTypeDef* DAC_InitStruct)
{
/*--------------- Reset DAC init structure parameters values -----------------*/
/* Initialize the DAC_Trigger member */
DAC_InitStruct->DAC_Trigger = DAC_Trigger_None;
/* Initialize the DAC_WaveGeneration member */
DAC_InitStruct->DAC_WaveGeneration = DAC_WaveGeneration_None;
/* Initialize the DAC_LFSRUnmask_TriangleAmplitude member */
DAC_InitStruct->DAC_LFSRUnmask_TriangleAmplitude = DAC_LFSRUnmask_Bit0;
/* Initialize the DAC_OutputBuffer member */
DAC_InitStruct->DAC_OutputBuffer = DAC_OutputBuffer_Enable;
}
/**
* @brief Enables or disables the specified DAC channel.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param NewState: new state of the DAC channel.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DAC_Cmd(uint32_t DAC_Channel, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected DAC channel */
DAC->CR |= (DAC_CR_EN1 << DAC_Channel);
}
else
{
/* Disable the selected DAC channel */
DAC->CR &= ~(DAC_CR_EN1 << DAC_Channel);
}
}
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
/**
* @brief Enables or disables the specified DAC interrupts.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param DAC_IT: specifies the DAC interrupt sources to be enabled or disabled.
* This parameter can be the following values:
* @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
* @param NewState: new state of the specified DAC interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DAC_ITConfig(uint32_t DAC_Channel, uint32_t DAC_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
assert_param(IS_FUNCTIONAL_STATE(NewState));
assert_param(IS_DAC_IT(DAC_IT));
if (NewState != DISABLE)
{
/* Enable the selected DAC interrupts */
DAC->CR |= (DAC_IT << DAC_Channel);
}
else
{
/* Disable the selected DAC interrupts */
DAC->CR &= (~(uint32_t)(DAC_IT << DAC_Channel));
}
}
#endif
/**
* @brief Enables or disables the specified DAC channel DMA request.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param NewState: new state of the selected DAC channel DMA request.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DAC_DMACmd(uint32_t DAC_Channel, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected DAC channel DMA request */
DAC->CR |= (DAC_CR_DMAEN1 << DAC_Channel);
}
else
{
/* Disable the selected DAC channel DMA request */
DAC->CR &= ~(DAC_CR_DMAEN1 << DAC_Channel);
}
}
/**
* @brief Enables or disables the selected DAC channel software trigger.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param NewState: new state of the selected DAC channel software trigger.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DAC_SoftwareTriggerCmd(uint32_t DAC_Channel, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable software trigger for the selected DAC channel */
DAC->SWTRIGR |= (uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4);
}
else
{
/* Disable software trigger for the selected DAC channel */
DAC->SWTRIGR &= ~((uint32_t)DAC_SWTRIGR_SWTRIG1 << (DAC_Channel >> 4));
}
}
/**
* @brief Enables or disables simultaneously the two DAC channels software
* triggers.
* @param NewState: new state of the DAC channels software triggers.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DAC_DualSoftwareTriggerCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable software trigger for both DAC channels */
DAC->SWTRIGR |= DUAL_SWTRIG_SET ;
}
else
{
/* Disable software trigger for both DAC channels */
DAC->SWTRIGR &= DUAL_SWTRIG_RESET;
}
}
/**
* @brief Enables or disables the selected DAC channel wave generation.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param DAC_Wave: Specifies the wave type to enable or disable.
* This parameter can be one of the following values:
* @arg DAC_Wave_Noise: noise wave generation
* @arg DAC_Wave_Triangle: triangle wave generation
* @param NewState: new state of the selected DAC channel wave generation.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DAC_WaveGenerationCmd(uint32_t DAC_Channel, uint32_t DAC_Wave, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
assert_param(IS_DAC_WAVE(DAC_Wave));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected wave generation for the selected DAC channel */
DAC->CR |= DAC_Wave << DAC_Channel;
}
else
{
/* Disable the selected wave generation for the selected DAC channel */
DAC->CR &= ~(DAC_Wave << DAC_Channel);
}
}
/**
* @brief Set the specified data holding register value for DAC channel1.
* @param DAC_Align: Specifies the data alignment for DAC channel1.
* This parameter can be one of the following values:
* @arg DAC_Align_8b_R: 8bit right data alignment selected
* @arg DAC_Align_12b_L: 12bit left data alignment selected
* @arg DAC_Align_12b_R: 12bit right data alignment selected
* @param Data : Data to be loaded in the selected data holding register.
* @retval None
*/
void DAC_SetChannel1Data(uint32_t DAC_Align, uint16_t Data)
{
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_DAC_ALIGN(DAC_Align));
assert_param(IS_DAC_DATA(Data));
tmp = (uint32_t)DAC_BASE;
tmp += DHR12R1_OFFSET + DAC_Align;
/* Set the DAC channel1 selected data holding register */
*(__IO uint32_t *) tmp = Data;
}
/**
* @brief Set the specified data holding register value for DAC channel2.
* @param DAC_Align: Specifies the data alignment for DAC channel2.
* This parameter can be one of the following values:
* @arg DAC_Align_8b_R: 8bit right data alignment selected
* @arg DAC_Align_12b_L: 12bit left data alignment selected
* @arg DAC_Align_12b_R: 12bit right data alignment selected
* @param Data : Data to be loaded in the selected data holding register.
* @retval None
*/
void DAC_SetChannel2Data(uint32_t DAC_Align, uint16_t Data)
{
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_DAC_ALIGN(DAC_Align));
assert_param(IS_DAC_DATA(Data));
tmp = (uint32_t)DAC_BASE;
tmp += DHR12R2_OFFSET + DAC_Align;
/* Set the DAC channel2 selected data holding register */
*(__IO uint32_t *)tmp = Data;
}
/**
* @brief Set the specified data holding register value for dual channel
* DAC.
* @param DAC_Align: Specifies the data alignment for dual channel DAC.
* This parameter can be one of the following values:
* @arg DAC_Align_8b_R: 8bit right data alignment selected
* @arg DAC_Align_12b_L: 12bit left data alignment selected
* @arg DAC_Align_12b_R: 12bit right data alignment selected
* @param Data2: Data for DAC Channel2 to be loaded in the selected data
* holding register.
* @param Data1: Data for DAC Channel1 to be loaded in the selected data
* holding register.
* @retval None
*/
void DAC_SetDualChannelData(uint32_t DAC_Align, uint16_t Data2, uint16_t Data1)
{
uint32_t data = 0, tmp = 0;
/* Check the parameters */
assert_param(IS_DAC_ALIGN(DAC_Align));
assert_param(IS_DAC_DATA(Data1));
assert_param(IS_DAC_DATA(Data2));
/* Calculate and set dual DAC data holding register value */
if (DAC_Align == DAC_Align_8b_R)
{
data = ((uint32_t)Data2 << 8) | Data1;
}
else
{
data = ((uint32_t)Data2 << 16) | Data1;
}
tmp = (uint32_t)DAC_BASE;
tmp += DHR12RD_OFFSET + DAC_Align;
/* Set the dual DAC selected data holding register */
*(__IO uint32_t *)tmp = data;
}
/**
* @brief Returns the last data output value of the selected DAC channel.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @retval The selected DAC channel data output value.
*/
uint16_t DAC_GetDataOutputValue(uint32_t DAC_Channel)
{
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
tmp = (uint32_t) DAC_BASE ;
tmp += DOR_OFFSET + ((uint32_t)DAC_Channel >> 2);
/* Returns the DAC channel data output register value */
return (uint16_t) (*(__IO uint32_t*) tmp);
}
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
/**
* @brief Checks whether the specified DAC flag is set or not.
* @param DAC_Channel: thee selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param DAC_FLAG: specifies the flag to check.
* This parameter can be only of the following value:
* @arg DAC_FLAG_DMAUDR: DMA underrun flag
* @retval The new state of DAC_FLAG (SET or RESET).
*/
FlagStatus DAC_GetFlagStatus(uint32_t DAC_Channel, uint32_t DAC_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
assert_param(IS_DAC_FLAG(DAC_FLAG));
/* Check the status of the specified DAC flag */
if ((DAC->SR & (DAC_FLAG << DAC_Channel)) != (uint8_t)RESET)
{
/* DAC_FLAG is set */
bitstatus = SET;
}
else
{
/* DAC_FLAG is reset */
bitstatus = RESET;
}
/* Return the DAC_FLAG status */
return bitstatus;
}
/**
* @brief Clears the DAC channelx's pending flags.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param DAC_FLAG: specifies the flag to clear.
* This parameter can be of the following value:
* @arg DAC_FLAG_DMAUDR: DMA underrun flag
* @retval None
*/
void DAC_ClearFlag(uint32_t DAC_Channel, uint32_t DAC_FLAG)
{
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
assert_param(IS_DAC_FLAG(DAC_FLAG));
/* Clear the selected DAC flags */
DAC->SR = (DAC_FLAG << DAC_Channel);
}
/**
* @brief Checks whether the specified DAC interrupt has occurred or not.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param DAC_IT: specifies the DAC interrupt source to check.
* This parameter can be the following values:
* @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
* @retval The new state of DAC_IT (SET or RESET).
*/
ITStatus DAC_GetITStatus(uint32_t DAC_Channel, uint32_t DAC_IT)
{
ITStatus bitstatus = RESET;
uint32_t enablestatus = 0;
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
assert_param(IS_DAC_IT(DAC_IT));
/* Get the DAC_IT enable bit status */
enablestatus = (DAC->CR & (DAC_IT << DAC_Channel)) ;
/* Check the status of the specified DAC interrupt */
if (((DAC->SR & (DAC_IT << DAC_Channel)) != (uint32_t)RESET) && enablestatus)
{
/* DAC_IT is set */
bitstatus = SET;
}
else
{
/* DAC_IT is reset */
bitstatus = RESET;
}
/* Return the DAC_IT status */
return bitstatus;
}
/**
* @brief Clears the DAC channelx's interrupt pending bits.
* @param DAC_Channel: the selected DAC channel.
* This parameter can be one of the following values:
* @arg DAC_Channel_1: DAC Channel1 selected
* @arg DAC_Channel_2: DAC Channel2 selected
* @param DAC_IT: specifies the DAC interrupt pending bit to clear.
* This parameter can be the following values:
* @arg DAC_IT_DMAUDR: DMA underrun interrupt mask
* @retval None
*/
void DAC_ClearITPendingBit(uint32_t DAC_Channel, uint32_t DAC_IT)
{
/* Check the parameters */
assert_param(IS_DAC_CHANNEL(DAC_Channel));
assert_param(IS_DAC_IT(DAC_IT));
/* Clear the selected DAC interrupt pending bits */
DAC->SR = (DAC_IT << DAC_Channel);
}
#endif
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_dbgmcu.c
================================================
/**
******************************************************************************
* @file stm32f10x_dbgmcu.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the DBGMCU firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_dbgmcu.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup DBGMCU
* @brief DBGMCU driver modules
* @{
*/
/** @defgroup DBGMCU_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup DBGMCU_Private_Defines
* @{
*/
#define IDCODE_DEVID_MASK ((uint32_t)0x00000FFF)
/**
* @}
*/
/** @defgroup DBGMCU_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup DBGMCU_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup DBGMCU_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup DBGMCU_Private_Functions
* @{
*/
/**
* @brief Returns the device revision identifier.
* @param None
* @retval Device revision identifier
*/
uint32_t DBGMCU_GetREVID(void)
{
return(DBGMCU->IDCODE >> 16);
}
/**
* @brief Returns the device identifier.
* @param None
* @retval Device identifier
*/
uint32_t DBGMCU_GetDEVID(void)
{
return(DBGMCU->IDCODE & IDCODE_DEVID_MASK);
}
/**
* @brief Configures the specified peripheral and low power mode behavior
* when the MCU under Debug mode.
* @param DBGMCU_Periph: specifies the peripheral and low power mode.
* This parameter can be any combination of the following values:
* @arg DBGMCU_SLEEP: Keep debugger connection during SLEEP mode
* @arg DBGMCU_STOP: Keep debugger connection during STOP mode
* @arg DBGMCU_STANDBY: Keep debugger connection during STANDBY mode
* @arg DBGMCU_IWDG_STOP: Debug IWDG stopped when Core is halted
* @arg DBGMCU_WWDG_STOP: Debug WWDG stopped when Core is halted
* @arg DBGMCU_TIM1_STOP: TIM1 counter stopped when Core is halted
* @arg DBGMCU_TIM2_STOP: TIM2 counter stopped when Core is halted
* @arg DBGMCU_TIM3_STOP: TIM3 counter stopped when Core is halted
* @arg DBGMCU_TIM4_STOP: TIM4 counter stopped when Core is halted
* @arg DBGMCU_CAN1_STOP: Debug CAN2 stopped when Core is halted
* @arg DBGMCU_I2C1_SMBUS_TIMEOUT: I2C1 SMBUS timeout mode stopped when Core is halted
* @arg DBGMCU_I2C2_SMBUS_TIMEOUT: I2C2 SMBUS timeout mode stopped when Core is halted
* @arg DBGMCU_TIM5_STOP: TIM5 counter stopped when Core is halted
* @arg DBGMCU_TIM6_STOP: TIM6 counter stopped when Core is halted
* @arg DBGMCU_TIM7_STOP: TIM7 counter stopped when Core is halted
* @arg DBGMCU_TIM8_STOP: TIM8 counter stopped when Core is halted
* @arg DBGMCU_CAN2_STOP: Debug CAN2 stopped when Core is halted
* @arg DBGMCU_TIM15_STOP: TIM15 counter stopped when Core is halted
* @arg DBGMCU_TIM16_STOP: TIM16 counter stopped when Core is halted
* @arg DBGMCU_TIM17_STOP: TIM17 counter stopped when Core is halted
* @arg DBGMCU_TIM9_STOP: TIM9 counter stopped when Core is halted
* @arg DBGMCU_TIM10_STOP: TIM10 counter stopped when Core is halted
* @arg DBGMCU_TIM11_STOP: TIM11 counter stopped when Core is halted
* @arg DBGMCU_TIM12_STOP: TIM12 counter stopped when Core is halted
* @arg DBGMCU_TIM13_STOP: TIM13 counter stopped when Core is halted
* @arg DBGMCU_TIM14_STOP: TIM14 counter stopped when Core is halted
* @param NewState: new state of the specified peripheral in Debug mode.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void DBGMCU_Config(uint32_t DBGMCU_Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_DBGMCU_PERIPH(DBGMCU_Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
DBGMCU->CR |= DBGMCU_Periph;
}
else
{
DBGMCU->CR &= ~DBGMCU_Periph;
}
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_dma.c
================================================
/**
******************************************************************************
* @file stm32f10x_dma.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the DMA firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_exti.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup EXTI
* @brief EXTI driver modules
* @{
*/
/** @defgroup EXTI_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup EXTI_Private_Defines
* @{
*/
#define EXTI_LINENONE ((uint32_t)0x00000) /* No interrupt selected */
/**
* @}
*/
/** @defgroup EXTI_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup EXTI_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup EXTI_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup EXTI_Private_Functions
* @{
*/
/**
* @brief Deinitializes the EXTI peripheral registers to their default reset values.
* @param None
* @retval None
*/
void EXTI_DeInit(void)
{
EXTI->IMR = 0x00000000;
EXTI->EMR = 0x00000000;
EXTI->RTSR = 0x00000000;
EXTI->FTSR = 0x00000000;
EXTI->PR = 0x000FFFFF;
}
/**
* @brief Initializes the EXTI peripheral according to the specified
* parameters in the EXTI_InitStruct.
* @param EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure
* that contains the configuration information for the EXTI peripheral.
* @retval None
*/
void EXTI_Init(EXTI_InitTypeDef* EXTI_InitStruct)
{
uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_EXTI_MODE(EXTI_InitStruct->EXTI_Mode));
assert_param(IS_EXTI_TRIGGER(EXTI_InitStruct->EXTI_Trigger));
assert_param(IS_EXTI_LINE(EXTI_InitStruct->EXTI_Line));
assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->EXTI_LineCmd));
tmp = (uint32_t)EXTI_BASE;
if (EXTI_InitStruct->EXTI_LineCmd != DISABLE)
{
/* Clear EXTI line configuration */
EXTI->IMR &= ~EXTI_InitStruct->EXTI_Line;
EXTI->EMR &= ~EXTI_InitStruct->EXTI_Line;
tmp += EXTI_InitStruct->EXTI_Mode;
*(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;
/* Clear Rising Falling edge configuration */
EXTI->RTSR &= ~EXTI_InitStruct->EXTI_Line;
EXTI->FTSR &= ~EXTI_InitStruct->EXTI_Line;
/* Select the trigger for the selected external interrupts */
if (EXTI_InitStruct->EXTI_Trigger == EXTI_Trigger_Rising_Falling)
{
/* Rising Falling edge */
EXTI->RTSR |= EXTI_InitStruct->EXTI_Line;
EXTI->FTSR |= EXTI_InitStruct->EXTI_Line;
}
else
{
tmp = (uint32_t)EXTI_BASE;
tmp += EXTI_InitStruct->EXTI_Trigger;
*(__IO uint32_t *) tmp |= EXTI_InitStruct->EXTI_Line;
}
}
else
{
tmp += EXTI_InitStruct->EXTI_Mode;
/* Disable the selected external lines */
*(__IO uint32_t *) tmp &= ~EXTI_InitStruct->EXTI_Line;
}
}
/**
* @brief Fills each EXTI_InitStruct member with its reset value.
* @param EXTI_InitStruct: pointer to a EXTI_InitTypeDef structure which will
* be initialized.
* @retval None
*/
void EXTI_StructInit(EXTI_InitTypeDef* EXTI_InitStruct)
{
EXTI_InitStruct->EXTI_Line = EXTI_LINENONE;
EXTI_InitStruct->EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct->EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStruct->EXTI_LineCmd = DISABLE;
}
/**
* @brief Generates a Software interrupt.
* @param EXTI_Line: specifies the EXTI lines to be enabled or disabled.
* This parameter can be any combination of EXTI_Linex where x can be (0..19).
* @retval None
*/
void EXTI_GenerateSWInterrupt(uint32_t EXTI_Line)
{
/* Check the parameters */
assert_param(IS_EXTI_LINE(EXTI_Line));
EXTI->SWIER |= EXTI_Line;
}
/**
* @brief Checks whether the specified EXTI line flag is set or not.
* @param EXTI_Line: specifies the EXTI line flag to check.
* This parameter can be:
* @arg EXTI_Linex: External interrupt line x where x(0..19)
* @retval The new state of EXTI_Line (SET or RESET).
*/
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_GET_EXTI_LINE(EXTI_Line));
if ((EXTI->PR & EXTI_Line) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the EXTI's line pending flags.
* @param EXTI_Line: specifies the EXTI lines flags to clear.
* This parameter can be any combination of EXTI_Linex where x can be (0..19).
* @retval None
*/
void EXTI_ClearFlag(uint32_t EXTI_Line)
{
/* Check the parameters */
assert_param(IS_EXTI_LINE(EXTI_Line));
EXTI->PR = EXTI_Line;
}
/**
* @brief Checks whether the specified EXTI line is asserted or not.
* @param EXTI_Line: specifies the EXTI line to check.
* This parameter can be:
* @arg EXTI_Linex: External interrupt line x where x(0..19)
* @retval The new state of EXTI_Line (SET or RESET).
*/
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line)
{
ITStatus bitstatus = RESET;
uint32_t enablestatus = 0;
/* Check the parameters */
assert_param(IS_GET_EXTI_LINE(EXTI_Line));
enablestatus = EXTI->IMR & EXTI_Line;
if (((EXTI->PR & EXTI_Line) != (uint32_t)RESET) && (enablestatus != (uint32_t)RESET))
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the EXTI's line pending bits.
* @param EXTI_Line: specifies the EXTI lines to clear.
* This parameter can be any combination of EXTI_Linex where x can be (0..19).
* @retval None
*/
void EXTI_ClearITPendingBit(uint32_t EXTI_Line)
{
/* Check the parameters */
assert_param(IS_EXTI_LINE(EXTI_Line));
EXTI->PR = EXTI_Line;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_flash.c
================================================
/**
******************************************************************************
* @file stm32f10x_flash.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the FLASH firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_flash.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup FLASH
* @brief FLASH driver modules
* @{
*/
/** @defgroup FLASH_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup FLASH_Private_Defines
* @{
*/
/* Flash Access Control Register bits */
#define ACR_LATENCY_Mask ((uint32_t)0x00000038)
#define ACR_HLFCYA_Mask ((uint32_t)0xFFFFFFF7)
#define ACR_PRFTBE_Mask ((uint32_t)0xFFFFFFEF)
/* Flash Access Control Register bits */
#define ACR_PRFTBS_Mask ((uint32_t)0x00000020)
/* Flash Control Register bits */
#define CR_PG_Set ((uint32_t)0x00000001)
#define CR_PG_Reset ((uint32_t)0x00001FFE)
#define CR_PER_Set ((uint32_t)0x00000002)
#define CR_PER_Reset ((uint32_t)0x00001FFD)
#define CR_MER_Set ((uint32_t)0x00000004)
#define CR_MER_Reset ((uint32_t)0x00001FFB)
#define CR_OPTPG_Set ((uint32_t)0x00000010)
#define CR_OPTPG_Reset ((uint32_t)0x00001FEF)
#define CR_OPTER_Set ((uint32_t)0x00000020)
#define CR_OPTER_Reset ((uint32_t)0x00001FDF)
#define CR_STRT_Set ((uint32_t)0x00000040)
#define CR_LOCK_Set ((uint32_t)0x00000080)
/* FLASH Mask */
#define RDPRT_Mask ((uint32_t)0x00000002)
#define WRP0_Mask ((uint32_t)0x000000FF)
#define WRP1_Mask ((uint32_t)0x0000FF00)
#define WRP2_Mask ((uint32_t)0x00FF0000)
#define WRP3_Mask ((uint32_t)0xFF000000)
#define OB_USER_BFB2 ((uint16_t)0x0008)
/* FLASH Keys */
#define RDP_Key ((uint16_t)0x00A5)
#define FLASH_KEY1 ((uint32_t)0x45670123)
#define FLASH_KEY2 ((uint32_t)0xCDEF89AB)
/* FLASH BANK address */
#define FLASH_BANK1_END_ADDRESS ((uint32_t)0x807FFFF)
/* Delay definition */
#define EraseTimeout ((uint32_t)0x000B0000)
#define ProgramTimeout ((uint32_t)0x00002000)
/**
* @}
*/
/** @defgroup FLASH_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup FLASH_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup FLASH_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup FLASH_Private_Functions
* @{
*/
/**
@code
This driver provides functions to configure and program the Flash memory of all STM32F10x devices,
including the latest STM32F10x_XL density devices.
STM32F10x_XL devices feature up to 1 Mbyte with dual bank architecture for read-while-write (RWW) capability:
- bank1: fixed size of 512 Kbytes (256 pages of 2Kbytes each)
- bank2: up to 512 Kbytes (up to 256 pages of 2Kbytes each)
While other STM32F10x devices features only one bank with memory up to 512 Kbytes.
In version V3.3.0, some functions were updated and new ones were added to support
STM32F10x_XL devices. Thus some functions manages all devices, while other are
dedicated for XL devices only.
The table below presents the list of available functions depending on the used STM32F10x devices.
***************************************************
* Legacy functions used for all STM32F10x devices *
***************************************************
+----------------------------------------------------------------------------------------------------------------------------------+
| Functions prototypes |STM32F10x_XL|Other STM32F10x| Comments |
| | devices | devices | |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_SetLatency | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_HalfCycleAccessCmd | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_PrefetchBufferCmd | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_Unlock | Yes | Yes | - For STM32F10X_XL devices: unlock Bank1 and Bank2. |
| | | | - For other devices: unlock Bank1 and it is equivalent |
| | | | to FLASH_UnlockBank1 function. |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_Lock | Yes | Yes | - For STM32F10X_XL devices: lock Bank1 and Bank2. |
| | | | - For other devices: lock Bank1 and it is equivalent |
| | | | to FLASH_LockBank1 function. |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_ErasePage | Yes | Yes | - For STM32F10x_XL devices: erase a page in Bank1 and Bank2 |
| | | | - For other devices: erase a page in Bank1 |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_EraseAllPages | Yes | Yes | - For STM32F10x_XL devices: erase all pages in Bank1 and Bank2 |
| | | | - For other devices: erase all pages in Bank1 |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_EraseOptionBytes | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_ProgramWord | Yes | Yes | Updated to program up to 1MByte (depending on the used device) |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_ProgramHalfWord | Yes | Yes | Updated to program up to 1MByte (depending on the used device) |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_ProgramOptionByteData | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_EnableWriteProtection | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_ReadOutProtection | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_UserOptionByteConfig | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_GetUserOptionByte | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_GetWriteProtectionOptionByte | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_GetReadOutProtectionStatus | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_GetPrefetchBufferStatus | Yes | Yes | No change |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_ITConfig | Yes | Yes | - For STM32F10x_XL devices: enable Bank1 and Bank2's interrupts|
| | | | - For other devices: enable Bank1's interrupts |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_GetFlagStatus | Yes | Yes | - For STM32F10x_XL devices: return Bank1 and Bank2's flag status|
| | | | - For other devices: return Bank1's flag status |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_ClearFlag | Yes | Yes | - For STM32F10x_XL devices: clear Bank1 and Bank2's flag |
| | | | - For other devices: clear Bank1's flag |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_GetStatus | Yes | Yes | - Return the status of Bank1 (for all devices) |
| | | | equivalent to FLASH_GetBank1Status function |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_WaitForLastOperation | Yes | Yes | - Wait for Bank1 last operation (for all devices) |
| | | | equivalent to: FLASH_WaitForLastBank1Operation function |
+----------------------------------------------------------------------------------------------------------------------------------+
************************************************************************************************************************
* New functions used for all STM32F10x devices to manage Bank1: *
* - These functions are mainly useful for STM32F10x_XL density devices, to have separate control for Bank1 and bank2 *
* - For other devices, these functions are optional (covered by functions listed above) *
************************************************************************************************************************
+----------------------------------------------------------------------------------------------------------------------------------+
| Functions prototypes |STM32F10x_XL|Other STM32F10x| Comments |
| | devices | devices | |
|----------------------------------------------------------------------------------------------------------------------------------|
| FLASH_UnlockBank1 | Yes | Yes | - Unlock Bank1 |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_LockBank1 | Yes | Yes | - Lock Bank1 |
|----------------------------------------------------------------------------------------------------------------------------------|
| FLASH_EraseAllBank1Pages | Yes | Yes | - Erase all pages in Bank1 |
|----------------------------------------------------------------------------------------------------------------------------------|
| FLASH_GetBank1Status | Yes | Yes | - Return the status of Bank1 |
|----------------------------------------------------------------------------------------------------------------------------------|
| FLASH_WaitForLastBank1Operation | Yes | Yes | - Wait for Bank1 last operation |
+----------------------------------------------------------------------------------------------------------------------------------+
*****************************************************************************
* New Functions used only with STM32F10x_XL density devices to manage Bank2 *
*****************************************************************************
+----------------------------------------------------------------------------------------------------------------------------------+
| Functions prototypes |STM32F10x_XL|Other STM32F10x| Comments |
| | devices | devices | |
|----------------------------------------------------------------------------------------------------------------------------------|
| FLASH_UnlockBank2 | Yes | No | - Unlock Bank2 |
|----------------------------------------------------------------------------------------------------------------------------------|
|FLASH_LockBank2 | Yes | No | - Lock Bank2 |
|----------------------------------------------------------------------------------------------------------------------------------|
| FLASH_EraseAllBank2Pages | Yes | No | - Erase all pages in Bank2 |
|----------------------------------------------------------------------------------------------------------------------------------|
| FLASH_GetBank2Status | Yes | No | - Return the status of Bank2 |
|----------------------------------------------------------------------------------------------------------------------------------|
| FLASH_WaitForLastBank2Operation | Yes | No | - Wait for Bank2 last operation |
|----------------------------------------------------------------------------------------------------------------------------------|
| FLASH_BootConfig | Yes | No | - Configure to boot from Bank1 or Bank2 |
+----------------------------------------------------------------------------------------------------------------------------------+
@endcode
*/
/**
* @brief Sets the code latency value.
* @note This function can be used for all STM32F10x devices.
* @param FLASH_Latency: specifies the FLASH Latency value.
* This parameter can be one of the following values:
* @arg FLASH_Latency_0: FLASH Zero Latency cycle
* @arg FLASH_Latency_1: FLASH One Latency cycle
* @arg FLASH_Latency_2: FLASH Two Latency cycles
* @retval None
*/
void FLASH_SetLatency(uint32_t FLASH_Latency)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_FLASH_LATENCY(FLASH_Latency));
/* Read the ACR register */
tmpreg = FLASH->ACR;
/* Sets the Latency value */
tmpreg &= ACR_LATENCY_Mask;
tmpreg |= FLASH_Latency;
/* Write the ACR register */
FLASH->ACR = tmpreg;
}
/**
* @brief Enables or disables the Half cycle flash access.
* @note This function can be used for all STM32F10x devices.
* @param FLASH_HalfCycleAccess: specifies the FLASH Half cycle Access mode.
* This parameter can be one of the following values:
* @arg FLASH_HalfCycleAccess_Enable: FLASH Half Cycle Enable
* @arg FLASH_HalfCycleAccess_Disable: FLASH Half Cycle Disable
* @retval None
*/
void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess)
{
/* Check the parameters */
assert_param(IS_FLASH_HALFCYCLEACCESS_STATE(FLASH_HalfCycleAccess));
/* Enable or disable the Half cycle access */
FLASH->ACR &= ACR_HLFCYA_Mask;
FLASH->ACR |= FLASH_HalfCycleAccess;
}
/**
* @brief Enables or disables the Prefetch Buffer.
* @note This function can be used for all STM32F10x devices.
* @param FLASH_PrefetchBuffer: specifies the Prefetch buffer status.
* This parameter can be one of the following values:
* @arg FLASH_PrefetchBuffer_Enable: FLASH Prefetch Buffer Enable
* @arg FLASH_PrefetchBuffer_Disable: FLASH Prefetch Buffer Disable
* @retval None
*/
void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer)
{
/* Check the parameters */
assert_param(IS_FLASH_PREFETCHBUFFER_STATE(FLASH_PrefetchBuffer));
/* Enable or disable the Prefetch Buffer */
FLASH->ACR &= ACR_PRFTBE_Mask;
FLASH->ACR |= FLASH_PrefetchBuffer;
}
/**
* @brief Unlocks the FLASH Program Erase Controller.
* @note This function can be used for all STM32F10x devices.
* - For STM32F10X_XL devices this function unlocks Bank1 and Bank2.
* - For all other devices it unlocks Bank1 and it is equivalent
* to FLASH_UnlockBank1 function..
* @param None
* @retval None
*/
void FLASH_Unlock(void)
{
/* Authorize the FPEC of Bank1 Access */
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
#ifdef STM32F10X_XL
/* Authorize the FPEC of Bank2 Access */
FLASH->KEYR2 = FLASH_KEY1;
FLASH->KEYR2 = FLASH_KEY2;
#endif /* STM32F10X_XL */
}
/**
* @brief Unlocks the FLASH Bank1 Program Erase Controller.
* @note This function can be used for all STM32F10x devices.
* - For STM32F10X_XL devices this function unlocks Bank1.
* - For all other devices it unlocks Bank1 and it is
* equivalent to FLASH_Unlock function.
* @param None
* @retval None
*/
void FLASH_UnlockBank1(void)
{
/* Authorize the FPEC of Bank1 Access */
FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2;
}
#ifdef STM32F10X_XL
/**
* @brief Unlocks the FLASH Bank2 Program Erase Controller.
* @note This function can be used only for STM32F10X_XL density devices.
* @param None
* @retval None
*/
void FLASH_UnlockBank2(void)
{
/* Authorize the FPEC of Bank2 Access */
FLASH->KEYR2 = FLASH_KEY1;
FLASH->KEYR2 = FLASH_KEY2;
}
#endif /* STM32F10X_XL */
/**
* @brief Locks the FLASH Program Erase Controller.
* @note This function can be used for all STM32F10x devices.
* - For STM32F10X_XL devices this function Locks Bank1 and Bank2.
* - For all other devices it Locks Bank1 and it is equivalent
* to FLASH_LockBank1 function.
* @param None
* @retval None
*/
void FLASH_Lock(void)
{
/* Set the Lock Bit to lock the FPEC and the CR of Bank1 */
FLASH->CR |= CR_LOCK_Set;
#ifdef STM32F10X_XL
/* Set the Lock Bit to lock the FPEC and the CR of Bank2 */
FLASH->CR2 |= CR_LOCK_Set;
#endif /* STM32F10X_XL */
}
/**
* @brief Locks the FLASH Bank1 Program Erase Controller.
* @note this function can be used for all STM32F10x devices.
* - For STM32F10X_XL devices this function Locks Bank1.
* - For all other devices it Locks Bank1 and it is equivalent
* to FLASH_Lock function.
* @param None
* @retval None
*/
void FLASH_LockBank1(void)
{
/* Set the Lock Bit to lock the FPEC and the CR of Bank1 */
FLASH->CR |= CR_LOCK_Set;
}
#ifdef STM32F10X_XL
/**
* @brief Locks the FLASH Bank2 Program Erase Controller.
* @note This function can be used only for STM32F10X_XL density devices.
* @param None
* @retval None
*/
void FLASH_LockBank2(void)
{
/* Set the Lock Bit to lock the FPEC and the CR of Bank2 */
FLASH->CR2 |= CR_LOCK_Set;
}
#endif /* STM32F10X_XL */
/**
* @brief Erases a specified FLASH page.
* @note This function can be used for all STM32F10x devices.
* @param Page_Address: The page address to be erased.
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
{
FLASH_Status status = FLASH_COMPLETE;
/* Check the parameters */
assert_param(IS_FLASH_ADDRESS(Page_Address));
#ifdef STM32F10X_XL
if(Page_Address < FLASH_BANK1_END_ADDRESS)
{
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase the page */
FLASH->CR|= CR_PER_Set;
FLASH->AR = Page_Address;
FLASH->CR|= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
/* Disable the PER Bit */
FLASH->CR &= CR_PER_Reset;
}
}
else
{
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase the page */
FLASH->CR2|= CR_PER_Set;
FLASH->AR2 = Page_Address;
FLASH->CR2|= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(EraseTimeout);
/* Disable the PER Bit */
FLASH->CR2 &= CR_PER_Reset;
}
}
#else
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase the page */
FLASH->CR|= CR_PER_Set;
FLASH->AR = Page_Address;
FLASH->CR|= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
/* Disable the PER Bit */
FLASH->CR &= CR_PER_Reset;
}
#endif /* STM32F10X_XL */
/* Return the Erase Status */
return status;
}
/**
* @brief Erases all FLASH pages.
* @note This function can be used for all STM32F10x devices.
* @param None
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_EraseAllPages(void)
{
FLASH_Status status = FLASH_COMPLETE;
#ifdef STM32F10X_XL
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase all pages */
FLASH->CR |= CR_MER_Set;
FLASH->CR |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
/* Disable the MER Bit */
FLASH->CR &= CR_MER_Reset;
}
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase all pages */
FLASH->CR2 |= CR_MER_Set;
FLASH->CR2 |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(EraseTimeout);
/* Disable the MER Bit */
FLASH->CR2 &= CR_MER_Reset;
}
#else
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase all pages */
FLASH->CR |= CR_MER_Set;
FLASH->CR |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
/* Disable the MER Bit */
FLASH->CR &= CR_MER_Reset;
}
#endif /* STM32F10X_XL */
/* Return the Erase Status */
return status;
}
/**
* @brief Erases all Bank1 FLASH pages.
* @note This function can be used for all STM32F10x devices.
* - For STM32F10X_XL devices this function erases all Bank1 pages.
* - For all other devices it erases all Bank1 pages and it is equivalent
* to FLASH_EraseAllPages function.
* @param None
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_EraseAllBank1Pages(void)
{
FLASH_Status status = FLASH_COMPLETE;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase all pages */
FLASH->CR |= CR_MER_Set;
FLASH->CR |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(EraseTimeout);
/* Disable the MER Bit */
FLASH->CR &= CR_MER_Reset;
}
/* Return the Erase Status */
return status;
}
#ifdef STM32F10X_XL
/**
* @brief Erases all Bank2 FLASH pages.
* @note This function can be used only for STM32F10x_XL density devices.
* @param None
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_EraseAllBank2Pages(void)
{
FLASH_Status status = FLASH_COMPLETE;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to erase all pages */
FLASH->CR2 |= CR_MER_Set;
FLASH->CR2 |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(EraseTimeout);
/* Disable the MER Bit */
FLASH->CR2 &= CR_MER_Reset;
}
/* Return the Erase Status */
return status;
}
#endif /* STM32F10X_XL */
/**
* @brief Erases the FLASH option bytes.
* @note This functions erases all option bytes except the Read protection (RDP).
* @note This function can be used for all STM32F10x devices.
* @param None
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_EraseOptionBytes(void)
{
uint16_t rdptmp = RDP_Key;
FLASH_Status status = FLASH_COMPLETE;
/* Get the actual read protection Option Byte value */
if(FLASH_GetReadOutProtectionStatus() != RESET)
{
rdptmp = 0x00;
}
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
/* if the previous operation is completed, proceed to erase the option bytes */
FLASH->CR |= CR_OPTER_Set;
FLASH->CR |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the erase operation is completed, disable the OPTER Bit */
FLASH->CR &= CR_OPTER_Reset;
/* Enable the Option Bytes Programming operation */
FLASH->CR |= CR_OPTPG_Set;
/* Restore the last read protection Option Byte value */
OB->RDP = (uint16_t)rdptmp;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status != FLASH_TIMEOUT)
{
/* if the program operation is completed, disable the OPTPG Bit */
FLASH->CR &= CR_OPTPG_Reset;
}
}
else
{
if (status != FLASH_TIMEOUT)
{
/* Disable the OPTPG Bit */
FLASH->CR &= CR_OPTPG_Reset;
}
}
}
/* Return the erase status */
return status;
}
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/**
* @brief Programs a word at a specified address.
* @note This function can be used for all STM32F10x devices.
* @param Address: specifies the address to be programmed.
* @param Data: specifies the data to be programmed.
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)
{
FLASH_Status status = FLASH_COMPLETE;
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_FLASH_ADDRESS(Address));
#ifdef STM32F10X_XL
if(Address < FLASH_BANK1_END_ADDRESS - 2)
{
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new first
half word */
FLASH->CR |= CR_PG_Set;
*(__IO uint16_t*)Address = (uint16_t)Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new second
half word */
tmp = Address + 2;
*(__IO uint16_t*) tmp = Data >> 16;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
/* Disable the PG Bit */
FLASH->CR &= CR_PG_Reset;
}
else
{
/* Disable the PG Bit */
FLASH->CR &= CR_PG_Reset;
}
}
}
else if(Address == (FLASH_BANK1_END_ADDRESS - 1))
{
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new first
half word */
FLASH->CR |= CR_PG_Set;
*(__IO uint16_t*)Address = (uint16_t)Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(ProgramTimeout);
/* Disable the PG Bit */
FLASH->CR &= CR_PG_Reset;
}
else
{
/* Disable the PG Bit */
FLASH->CR &= CR_PG_Reset;
}
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new second
half word */
FLASH->CR2 |= CR_PG_Set;
tmp = Address + 2;
*(__IO uint16_t*) tmp = Data >> 16;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
/* Disable the PG Bit */
FLASH->CR2 &= CR_PG_Reset;
}
else
{
/* Disable the PG Bit */
FLASH->CR2 &= CR_PG_Reset;
}
}
else
{
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new first
half word */
FLASH->CR2 |= CR_PG_Set;
*(__IO uint16_t*)Address = (uint16_t)Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new second
half word */
tmp = Address + 2;
*(__IO uint16_t*) tmp = Data >> 16;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
/* Disable the PG Bit */
FLASH->CR2 &= CR_PG_Reset;
}
else
{
/* Disable the PG Bit */
FLASH->CR2 &= CR_PG_Reset;
}
}
}
#else
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new first
half word */
FLASH->CR |= CR_PG_Set;
*(__IO uint16_t*)Address = (uint16_t)Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new second
half word */
tmp = Address + 2;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
*(__IO uint16_t*) tmp = Data >> 16;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
/* Disable the PG Bit */
FLASH->CR &= CR_PG_Reset;
}
else
{
/* Disable the PG Bit */
FLASH->CR &= CR_PG_Reset;
}
}
#endif /* STM32F10X_XL */
/* Return the Program Status */
return status;
}
// [ILG]
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
/**
* @brief Programs a half word at a specified address.
* @note This function can be used for all STM32F10x devices.
* @param Address: specifies the address to be programmed.
* @param Data: specifies the data to be programmed.
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{
FLASH_Status status = FLASH_COMPLETE;
/* Check the parameters */
assert_param(IS_FLASH_ADDRESS(Address));
#ifdef STM32F10X_XL
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(Address < FLASH_BANK1_END_ADDRESS)
{
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new data */
FLASH->CR |= CR_PG_Set;
*(__IO uint16_t*)Address = Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank1Operation(ProgramTimeout);
/* Disable the PG Bit */
FLASH->CR &= CR_PG_Reset;
}
}
else
{
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new data */
FLASH->CR2 |= CR_PG_Set;
*(__IO uint16_t*)Address = Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
/* Disable the PG Bit */
FLASH->CR2 &= CR_PG_Reset;
}
}
#else
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* if the previous operation is completed, proceed to program the new data */
FLASH->CR |= CR_PG_Set;
*(__IO uint16_t*)Address = Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
/* Disable the PG Bit */
FLASH->CR &= CR_PG_Reset;
}
#endif /* STM32F10X_XL */
/* Return the Program Status */
return status;
}
/**
* @brief Programs a half word at a specified Option Byte Data address.
* @note This function can be used for all STM32F10x devices.
* @param Address: specifies the address to be programmed.
* This parameter can be 0x1FFFF804 or 0x1FFFF806.
* @param Data: specifies the data to be programmed.
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data)
{
FLASH_Status status = FLASH_COMPLETE;
/* Check the parameters */
assert_param(IS_OB_DATA_ADDRESS(Address));
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
/* Enables the Option Bytes Programming operation */
FLASH->CR |= CR_OPTPG_Set;
*(__IO uint16_t*)Address = Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status != FLASH_TIMEOUT)
{
/* if the program operation is completed, disable the OPTPG Bit */
FLASH->CR &= CR_OPTPG_Reset;
}
}
/* Return the Option Byte Data Program Status */
return status;
}
/**
* @brief Write protects the desired pages
* @note This function can be used for all STM32F10x devices.
* @param FLASH_Pages: specifies the address of the pages to be write protected.
* This parameter can be:
* @arg For @b STM32_Low-density_devices: value between FLASH_WRProt_Pages0to3 and FLASH_WRProt_Pages28to31
* @arg For @b STM32_Medium-density_devices: value between FLASH_WRProt_Pages0to3
* and FLASH_WRProt_Pages124to127
* @arg For @b STM32_High-density_devices: value between FLASH_WRProt_Pages0to1 and
* FLASH_WRProt_Pages60to61 or FLASH_WRProt_Pages62to255
* @arg For @b STM32_Connectivity_line_devices: value between FLASH_WRProt_Pages0to1 and
* FLASH_WRProt_Pages60to61 or FLASH_WRProt_Pages62to127
* @arg For @b STM32_XL-density_devices: value between FLASH_WRProt_Pages0to1 and
* FLASH_WRProt_Pages60to61 or FLASH_WRProt_Pages62to511
* @arg FLASH_WRProt_AllPages
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages)
{
uint16_t WRP0_Data = 0xFFFF, WRP1_Data = 0xFFFF, WRP2_Data = 0xFFFF, WRP3_Data = 0xFFFF;
FLASH_Status status = FLASH_COMPLETE;
/* Check the parameters */
assert_param(IS_FLASH_WRPROT_PAGE(FLASH_Pages));
FLASH_Pages = (uint32_t)(~FLASH_Pages);
WRP0_Data = (uint16_t)(FLASH_Pages & WRP0_Mask);
WRP1_Data = (uint16_t)((FLASH_Pages & WRP1_Mask) >> 8);
WRP2_Data = (uint16_t)((FLASH_Pages & WRP2_Mask) >> 16);
WRP3_Data = (uint16_t)((FLASH_Pages & WRP3_Mask) >> 24);
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* Authorizes the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
FLASH->CR |= CR_OPTPG_Set;
if(WRP0_Data != 0xFF)
{
OB->WRP0 = WRP0_Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
}
if((status == FLASH_COMPLETE) && (WRP1_Data != 0xFF))
{
OB->WRP1 = WRP1_Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
}
if((status == FLASH_COMPLETE) && (WRP2_Data != 0xFF))
{
OB->WRP2 = WRP2_Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
}
if((status == FLASH_COMPLETE)&& (WRP3_Data != 0xFF))
{
OB->WRP3 = WRP3_Data;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
}
if(status != FLASH_TIMEOUT)
{
/* if the program operation is completed, disable the OPTPG Bit */
FLASH->CR &= CR_OPTPG_Reset;
}
}
/* Return the write protection operation Status */
return status;
}
/**
* @brief Enables or disables the read out protection.
* @note If the user has already programmed the other option bytes before calling
* this function, he must re-program them since this function erases all option bytes.
* @note This function can be used for all STM32F10x devices.
* @param Newstate: new state of the ReadOut Protection.
* This parameter can be: ENABLE or DISABLE.
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState)
{
FLASH_Status status = FLASH_COMPLETE;
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* Authorizes the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
FLASH->CR |= CR_OPTER_Set;
FLASH->CR |= CR_STRT_Set;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status == FLASH_COMPLETE)
{
/* if the erase operation is completed, disable the OPTER Bit */
FLASH->CR &= CR_OPTER_Reset;
/* Enable the Option Bytes Programming operation */
FLASH->CR |= CR_OPTPG_Set;
if(NewState != DISABLE)
{
OB->RDP = 0x00;
}
else
{
OB->RDP = RDP_Key;
}
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(EraseTimeout);
if(status != FLASH_TIMEOUT)
{
/* if the program operation is completed, disable the OPTPG Bit */
FLASH->CR &= CR_OPTPG_Reset;
}
}
else
{
if(status != FLASH_TIMEOUT)
{
/* Disable the OPTER Bit */
FLASH->CR &= CR_OPTER_Reset;
}
}
}
/* Return the protection operation Status */
return status;
}
/**
* @brief Programs the FLASH User Option Byte: IWDG_SW / RST_STOP / RST_STDBY.
* @note This function can be used for all STM32F10x devices.
* @param OB_IWDG: Selects the IWDG mode
* This parameter can be one of the following values:
* @arg OB_IWDG_SW: Software IWDG selected
* @arg OB_IWDG_HW: Hardware IWDG selected
* @param OB_STOP: Reset event when entering STOP mode.
* This parameter can be one of the following values:
* @arg OB_STOP_NoRST: No reset generated when entering in STOP
* @arg OB_STOP_RST: Reset generated when entering in STOP
* @param OB_STDBY: Reset event when entering Standby mode.
* This parameter can be one of the following values:
* @arg OB_STDBY_NoRST: No reset generated when entering in STANDBY
* @arg OB_STDBY_RST: Reset generated when entering in STANDBY
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY)
{
FLASH_Status status = FLASH_COMPLETE;
/* Check the parameters */
assert_param(IS_OB_IWDG_SOURCE(OB_IWDG));
assert_param(IS_OB_STOP_SOURCE(OB_STOP));
assert_param(IS_OB_STDBY_SOURCE(OB_STDBY));
/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* Enable the Option Bytes Programming operation */
FLASH->CR |= CR_OPTPG_Set;
OB->USER = OB_IWDG | (uint16_t)(OB_STOP | (uint16_t)(OB_STDBY | ((uint16_t)0xF8)));
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status != FLASH_TIMEOUT)
{
/* if the program operation is completed, disable the OPTPG Bit */
FLASH->CR &= CR_OPTPG_Reset;
}
}
/* Return the Option Byte program Status */
return status;
}
#ifdef STM32F10X_XL
/**
* @brief Configures to boot from Bank1 or Bank2.
* @note This function can be used only for STM32F10x_XL density devices.
* @param FLASH_BOOT: select the FLASH Bank to boot from.
* This parameter can be one of the following values:
* @arg FLASH_BOOT_Bank1: At startup, if boot pins are set in boot from user Flash
* position and this parameter is selected the device will boot from Bank1(Default).
* @arg FLASH_BOOT_Bank2: At startup, if boot pins are set in boot from user Flash
* position and this parameter is selected the device will boot from Bank2 or Bank1,
* depending on the activation of the bank. The active banks are checked in
* the following order: Bank2, followed by Bank1.
* The active bank is recognized by the value programmed at the base address
* of the respective bank (corresponding to the initial stack pointer value
* in the interrupt vector table).
* For more information, please refer to AN2606 from www.st.com.
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_BootConfig(uint16_t FLASH_BOOT)
{
FLASH_Status status = FLASH_COMPLETE;
assert_param(IS_FLASH_BOOT(FLASH_BOOT));
/* Authorize the small information block programming */
FLASH->OPTKEYR = FLASH_KEY1;
FLASH->OPTKEYR = FLASH_KEY2;
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status == FLASH_COMPLETE)
{
/* Enable the Option Bytes Programming operation */
FLASH->CR |= CR_OPTPG_Set;
if(FLASH_BOOT == FLASH_BOOT_Bank1)
{
OB->USER |= OB_USER_BFB2;
}
else
{
OB->USER &= (uint16_t)(~(uint16_t)(OB_USER_BFB2));
}
/* Wait for last operation to be completed */
status = FLASH_WaitForLastOperation(ProgramTimeout);
if(status != FLASH_TIMEOUT)
{
/* if the program operation is completed, disable the OPTPG Bit */
FLASH->CR &= CR_OPTPG_Reset;
}
}
/* Return the Option Byte program Status */
return status;
}
#endif /* STM32F10X_XL */
/**
* @brief Returns the FLASH User Option Bytes values.
* @note This function can be used for all STM32F10x devices.
* @param None
* @retval The FLASH User Option Bytes values:IWDG_SW(Bit0), RST_STOP(Bit1)
* and RST_STDBY(Bit2).
*/
uint32_t FLASH_GetUserOptionByte(void)
{
/* Return the User Option Byte */
return (uint32_t)(FLASH->OBR >> 2);
}
/**
* @brief Returns the FLASH Write Protection Option Bytes Register value.
* @note This function can be used for all STM32F10x devices.
* @param None
* @retval The FLASH Write Protection Option Bytes Register value
*/
uint32_t FLASH_GetWriteProtectionOptionByte(void)
{
/* Return the Flash write protection Register value */
return (uint32_t)(FLASH->WRPR);
}
/**
* @brief Checks whether the FLASH Read Out Protection Status is set or not.
* @note This function can be used for all STM32F10x devices.
* @param None
* @retval FLASH ReadOut Protection Status(SET or RESET)
*/
FlagStatus FLASH_GetReadOutProtectionStatus(void)
{
FlagStatus readoutstatus = RESET;
if ((FLASH->OBR & RDPRT_Mask) != (uint32_t)RESET)
{
readoutstatus = SET;
}
else
{
readoutstatus = RESET;
}
return readoutstatus;
}
/**
* @brief Checks whether the FLASH Prefetch Buffer status is set or not.
* @note This function can be used for all STM32F10x devices.
* @param None
* @retval FLASH Prefetch Buffer Status (SET or RESET).
*/
FlagStatus FLASH_GetPrefetchBufferStatus(void)
{
FlagStatus bitstatus = RESET;
if ((FLASH->ACR & ACR_PRFTBS_Mask) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
/* Return the new state of FLASH Prefetch Buffer Status (SET or RESET) */
return bitstatus;
}
/**
* @brief Enables or disables the specified FLASH interrupts.
* @note This function can be used for all STM32F10x devices.
* - For STM32F10X_XL devices, enables or disables the specified FLASH interrupts
for Bank1 and Bank2.
* - For other devices it enables or disables the specified FLASH interrupts for Bank1.
* @param FLASH_IT: specifies the FLASH interrupt sources to be enabled or disabled.
* This parameter can be any combination of the following values:
* @arg FLASH_IT_ERROR: FLASH Error Interrupt
* @arg FLASH_IT_EOP: FLASH end of operation Interrupt
* @param NewState: new state of the specified Flash interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState)
{
#ifdef STM32F10X_XL
/* Check the parameters */
assert_param(IS_FLASH_IT(FLASH_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if((FLASH_IT & 0x80000000) != 0x0)
{
if(NewState != DISABLE)
{
/* Enable the interrupt sources */
FLASH->CR2 |= (FLASH_IT & 0x7FFFFFFF);
}
else
{
/* Disable the interrupt sources */
FLASH->CR2 &= ~(uint32_t)(FLASH_IT & 0x7FFFFFFF);
}
}
else
{
if(NewState != DISABLE)
{
/* Enable the interrupt sources */
FLASH->CR |= FLASH_IT;
}
else
{
/* Disable the interrupt sources */
FLASH->CR &= ~(uint32_t)FLASH_IT;
}
}
#else
/* Check the parameters */
assert_param(IS_FLASH_IT(FLASH_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if(NewState != DISABLE)
{
/* Enable the interrupt sources */
FLASH->CR |= FLASH_IT;
}
else
{
/* Disable the interrupt sources */
FLASH->CR &= ~(uint32_t)FLASH_IT;
}
#endif /* STM32F10X_XL */
}
/**
* @brief Checks whether the specified FLASH flag is set or not.
* @note This function can be used for all STM32F10x devices.
* - For STM32F10X_XL devices, this function checks whether the specified
* Bank1 or Bank2 flag is set or not.
* - For other devices, it checks whether the specified Bank1 flag is
* set or not.
* @param FLASH_FLAG: specifies the FLASH flag to check.
* This parameter can be one of the following values:
* @arg FLASH_FLAG_BSY: FLASH Busy flag
* @arg FLASH_FLAG_PGERR: FLASH Program error flag
* @arg FLASH_FLAG_WRPRTERR: FLASH Write protected error flag
* @arg FLASH_FLAG_EOP: FLASH End of Operation flag
* @arg FLASH_FLAG_OPTERR: FLASH Option Byte error flag
* @retval The new state of FLASH_FLAG (SET or RESET).
*/
FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG)
{
FlagStatus bitstatus = RESET;
#ifdef STM32F10X_XL
/* Check the parameters */
assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)) ;
if(FLASH_FLAG == FLASH_FLAG_OPTERR)
{
if((FLASH->OBR & FLASH_FLAG_OPTERR) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
}
else
{
if((FLASH_FLAG & 0x80000000) != 0x0)
{
if((FLASH->SR2 & FLASH_FLAG) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
}
else
{
if((FLASH->SR & FLASH_FLAG) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
}
}
#else
/* Check the parameters */
assert_param(IS_FLASH_GET_FLAG(FLASH_FLAG)) ;
if(FLASH_FLAG == FLASH_FLAG_OPTERR)
{
if((FLASH->OBR & FLASH_FLAG_OPTERR) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
}
else
{
if((FLASH->SR & FLASH_FLAG) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
}
#endif /* STM32F10X_XL */
/* Return the new state of FLASH_FLAG (SET or RESET) */
return bitstatus;
}
/**
* @brief Clears the FLASH's pending flags.
* @note This function can be used for all STM32F10x devices.
* - For STM32F10X_XL devices, this function clears Bank1 or Bank2�s pending flags
* - For other devices, it clears Bank1�s pending flags.
* @param FLASH_FLAG: specifies the FLASH flags to clear.
* This parameter can be any combination of the following values:
* @arg FLASH_FLAG_PGERR: FLASH Program error flag
* @arg FLASH_FLAG_WRPRTERR: FLASH Write protected error flag
* @arg FLASH_FLAG_EOP: FLASH End of Operation flag
* @retval None
*/
void FLASH_ClearFlag(uint32_t FLASH_FLAG)
{
#ifdef STM32F10X_XL
/* Check the parameters */
assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)) ;
if((FLASH_FLAG & 0x80000000) != 0x0)
{
/* Clear the flags */
FLASH->SR2 = FLASH_FLAG;
}
else
{
/* Clear the flags */
FLASH->SR = FLASH_FLAG;
}
#else
/* Check the parameters */
assert_param(IS_FLASH_CLEAR_FLAG(FLASH_FLAG)) ;
/* Clear the flags */
FLASH->SR = FLASH_FLAG;
#endif /* STM32F10X_XL */
}
/**
* @brief Returns the FLASH Status.
* @note This function can be used for all STM32F10x devices, it is equivalent
* to FLASH_GetBank1Status function.
* @param None
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP or FLASH_COMPLETE
*/
FLASH_Status FLASH_GetStatus(void)
{
FLASH_Status flashstatus = FLASH_COMPLETE;
if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY)
{
flashstatus = FLASH_BUSY;
}
else
{
if((FLASH->SR & FLASH_FLAG_PGERR) != 0)
{
flashstatus = FLASH_ERROR_PG;
}
else
{
if((FLASH->SR & FLASH_FLAG_WRPRTERR) != 0 )
{
flashstatus = FLASH_ERROR_WRP;
}
else
{
flashstatus = FLASH_COMPLETE;
}
}
}
/* Return the Flash Status */
return flashstatus;
}
/**
* @brief Returns the FLASH Bank1 Status.
* @note This function can be used for all STM32F10x devices, it is equivalent
* to FLASH_GetStatus function.
* @param None
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP or FLASH_COMPLETE
*/
FLASH_Status FLASH_GetBank1Status(void)
{
FLASH_Status flashstatus = FLASH_COMPLETE;
if((FLASH->SR & FLASH_FLAG_BANK1_BSY) == FLASH_FLAG_BSY)
{
flashstatus = FLASH_BUSY;
}
else
{
if((FLASH->SR & FLASH_FLAG_BANK1_PGERR) != 0)
{
flashstatus = FLASH_ERROR_PG;
}
else
{
if((FLASH->SR & FLASH_FLAG_BANK1_WRPRTERR) != 0 )
{
flashstatus = FLASH_ERROR_WRP;
}
else
{
flashstatus = FLASH_COMPLETE;
}
}
}
/* Return the Flash Status */
return flashstatus;
}
#ifdef STM32F10X_XL
/**
* @brief Returns the FLASH Bank2 Status.
* @note This function can be used for STM32F10x_XL density devices.
* @param None
* @retval FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP or FLASH_COMPLETE
*/
FLASH_Status FLASH_GetBank2Status(void)
{
FLASH_Status flashstatus = FLASH_COMPLETE;
if((FLASH->SR2 & (FLASH_FLAG_BANK2_BSY & 0x7FFFFFFF)) == (FLASH_FLAG_BANK2_BSY & 0x7FFFFFFF))
{
flashstatus = FLASH_BUSY;
}
else
{
if((FLASH->SR2 & (FLASH_FLAG_BANK2_PGERR & 0x7FFFFFFF)) != 0)
{
flashstatus = FLASH_ERROR_PG;
}
else
{
if((FLASH->SR2 & (FLASH_FLAG_BANK2_WRPRTERR & 0x7FFFFFFF)) != 0 )
{
flashstatus = FLASH_ERROR_WRP;
}
else
{
flashstatus = FLASH_COMPLETE;
}
}
}
/* Return the Flash Status */
return flashstatus;
}
#endif /* STM32F10X_XL */
/**
* @brief Waits for a Flash operation to complete or a TIMEOUT to occur.
* @note This function can be used for all STM32F10x devices,
* it is equivalent to FLASH_WaitForLastBank1Operation.
* - For STM32F10X_XL devices this function waits for a Bank1 Flash operation
* to complete or a TIMEOUT to occur.
* - For all other devices it waits for a Flash operation to complete
* or a TIMEOUT to occur.
* @param Timeout: FLASH programming Timeout
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout)
{
FLASH_Status status = FLASH_COMPLETE;
/* Check for the Flash Status */
status = FLASH_GetBank1Status();
/* Wait for a Flash operation to complete or a TIMEOUT to occur */
while((status == FLASH_BUSY) && (Timeout != 0x00))
{
status = FLASH_GetBank1Status();
Timeout--;
}
if(Timeout == 0x00 )
{
status = FLASH_TIMEOUT;
}
/* Return the operation status */
return status;
}
/**
* @brief Waits for a Flash operation on Bank1 to complete or a TIMEOUT to occur.
* @note This function can be used for all STM32F10x devices,
* it is equivalent to FLASH_WaitForLastOperation.
* @param Timeout: FLASH programming Timeout
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_WaitForLastBank1Operation(uint32_t Timeout)
{
FLASH_Status status = FLASH_COMPLETE;
/* Check for the Flash Status */
status = FLASH_GetBank1Status();
/* Wait for a Flash operation to complete or a TIMEOUT to occur */
while((status == FLASH_FLAG_BANK1_BSY) && (Timeout != 0x00))
{
status = FLASH_GetBank1Status();
Timeout--;
}
if(Timeout == 0x00 )
{
status = FLASH_TIMEOUT;
}
/* Return the operation status */
return status;
}
#ifdef STM32F10X_XL
/**
* @brief Waits for a Flash operation on Bank2 to complete or a TIMEOUT to occur.
* @note This function can be used only for STM32F10x_XL density devices.
* @param Timeout: FLASH programming Timeout
* @retval FLASH Status: The returned value can be: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_WaitForLastBank2Operation(uint32_t Timeout)
{
FLASH_Status status = FLASH_COMPLETE;
/* Check for the Flash Status */
status = FLASH_GetBank2Status();
/* Wait for a Flash operation to complete or a TIMEOUT to occur */
while((status == (FLASH_FLAG_BANK2_BSY & 0x7FFFFFFF)) && (Timeout != 0x00))
{
status = FLASH_GetBank2Status();
Timeout--;
}
if(Timeout == 0x00 )
{
status = FLASH_TIMEOUT;
}
/* Return the operation status */
return status;
}
#endif /* STM32F10X_XL */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_fsmc.c
================================================
/**
******************************************************************************
* @file stm32f10x_fsmc.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the FSMC firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup GPIO
* @brief GPIO driver modules
* @{
*/
/** @defgroup GPIO_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup GPIO_Private_Defines
* @{
*/
/* ------------ RCC registers bit address in the alias region ----------------*/
#define AFIO_OFFSET (AFIO_BASE - PERIPH_BASE)
/* --- EVENTCR Register -----*/
/* Alias word address of EVOE bit */
#define EVCR_OFFSET (AFIO_OFFSET + 0x00)
#define EVOE_BitNumber ((uint8_t)0x07)
#define EVCR_EVOE_BB (PERIPH_BB_BASE + (EVCR_OFFSET * 32) + (EVOE_BitNumber * 4))
/* --- MAPR Register ---*/
/* Alias word address of MII_RMII_SEL bit */
#define MAPR_OFFSET (AFIO_OFFSET + 0x04)
#define MII_RMII_SEL_BitNumber ((u8)0x17)
#define MAPR_MII_RMII_SEL_BB (PERIPH_BB_BASE + (MAPR_OFFSET * 32) + (MII_RMII_SEL_BitNumber * 4))
#define EVCR_PORTPINCONFIG_MASK ((uint16_t)0xFF80)
#define LSB_MASK ((uint16_t)0xFFFF)
#define DBGAFR_POSITION_MASK ((uint32_t)0x000F0000)
#define DBGAFR_SWJCFG_MASK ((uint32_t)0xF0FFFFFF)
#define DBGAFR_LOCATION_MASK ((uint32_t)0x00200000)
#define DBGAFR_NUMBITS_MASK ((uint32_t)0x00100000)
/**
* @}
*/
/** @defgroup GPIO_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup GPIO_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup GPIO_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup GPIO_Private_Functions
* @{
*/
/**
* @brief Deinitializes the GPIOx peripheral registers to their default reset values.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @retval None
*/
void GPIO_DeInit(GPIO_TypeDef* GPIOx)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
if (GPIOx == GPIOA)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOA, DISABLE);
}
else if (GPIOx == GPIOB)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);
}
else if (GPIOx == GPIOC)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE);
}
else if (GPIOx == GPIOD)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOD, DISABLE);
}
else if (GPIOx == GPIOE)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOE, DISABLE);
}
else if (GPIOx == GPIOF)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOF, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOF, DISABLE);
}
else
{
if (GPIOx == GPIOG)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOG, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOG, DISABLE);
}
}
}
/**
* @brief Deinitializes the Alternate Functions (remap, event control
* and EXTI configuration) registers to their default reset values.
* @param None
* @retval None
*/
void GPIO_AFIODeInit(void)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_AFIO, DISABLE);
}
/**
* @brief Initializes the GPIOx peripheral according to the specified
* parameters in the GPIO_InitStruct.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that
* contains the configuration information for the specified GPIO peripheral.
* @retval None
*/
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
uint32_t tmpreg = 0x00, pinmask = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));
/*---------------------------- GPIO Mode Configuration -----------------------*/
currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
{
/* Check the parameters */
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
/* Output mode */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
}
/*---------------------------- GPIO CRL Configuration ------------------------*/
/* Configure the eight low port pins */
if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
{
tmpreg = GPIOx->CRL;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = ((uint32_t)0x01) << pinpos;
/* Get the port pins position */
currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
if (currentpin == pos)
{
pos = pinpos << 2;
/* Clear the corresponding low control register bits */
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos);
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << pinpos);
}
else
{
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
}
}
}
}
GPIOx->CRL = tmpreg;
}
/*---------------------------- GPIO CRH Configuration ------------------------*/
/* Configure the eight high port pins */
if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
{
tmpreg = GPIOx->CRH;
for (pinpos = 0x00; pinpos < 0x08; pinpos++)
{
pos = (((uint32_t)0x01) << (pinpos + 0x08));
/* Get the port pins position */
currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
if (currentpin == pos)
{
pos = pinpos << 2;
/* Clear the corresponding high control register bits */
pinmask = ((uint32_t)0x0F) << pos;
tmpreg &= ~pinmask;
/* Write the mode configuration in the corresponding bits */
tmpreg |= (currentmode << pos);
/* Reset the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
{
GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
/* Set the corresponding ODR bit */
if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
{
GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
}
}
}
GPIOx->CRH = tmpreg;
}
}
/**
* @brief Fills each GPIO_InitStruct member with its default value.
* @param GPIO_InitStruct : pointer to a GPIO_InitTypeDef structure which will
* be initialized.
* @retval None
*/
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)
{
/* Reset GPIO init structure parameters values */
GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All;
GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz;
GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN_FLOATING;
}
/**
* @brief Reads the specified input port pin.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bit to read.
* This parameter can be GPIO_Pin_x where x can be (0..15).
* @retval The input port pin value.
*/
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}
/**
* @brief Reads the specified GPIO input data port.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @retval GPIO input data port value.
*/
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
return ((uint16_t)GPIOx->IDR);
}
/**
* @brief Reads the specified output data port bit.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bit to read.
* This parameter can be GPIO_Pin_x where x can be (0..15).
* @retval The output port pin value.
*/
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
if ((GPIOx->ODR & GPIO_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
}
else
{
bitstatus = (uint8_t)Bit_RESET;
}
return bitstatus;
}
/**
* @brief Reads the specified GPIO output data port.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @retval GPIO output data port value.
*/
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
return ((uint16_t)GPIOx->ODR);
}
/**
* @brief Sets the selected data port bits.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bits to be written.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval None
*/
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BSRR = GPIO_Pin;
}
/**
* @brief Clears the selected data port bits.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bits to be written.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval None
*/
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
GPIOx->BRR = GPIO_Pin;
}
/**
* @brief Sets or clears the selected data port bit.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be one of GPIO_Pin_x where x can be (0..15).
* @param BitVal: specifies the value to be written to the selected bit.
* This parameter can be one of the BitAction enum values:
* @arg Bit_RESET: to clear the port pin
* @arg Bit_SET: to set the port pin
* @retval None
*/
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GET_GPIO_PIN(GPIO_Pin));
assert_param(IS_GPIO_BIT_ACTION(BitVal));
if (BitVal != Bit_RESET)
{
GPIOx->BSRR = GPIO_Pin;
}
else
{
GPIOx->BRR = GPIO_Pin;
}
}
/**
* @brief Writes data to the specified GPIO data port.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param PortVal: specifies the value to be written to the port output data register.
* @retval None
*/
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
{
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
GPIOx->ODR = PortVal;
}
/**
* @brief Locks GPIO Pins configuration registers.
* @param GPIOx: where x can be (A..G) to select the GPIO peripheral.
* @param GPIO_Pin: specifies the port bit to be written.
* This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
* @retval None
*/
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint32_t tmp = 0x00010000;
/* Check the parameters */
assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
assert_param(IS_GPIO_PIN(GPIO_Pin));
tmp |= GPIO_Pin;
/* Set LCKK bit */
GPIOx->LCKR = tmp;
/* Reset LCKK bit */
GPIOx->LCKR = GPIO_Pin;
/* Set LCKK bit */
GPIOx->LCKR = tmp;
/* Read LCKK bit*/
tmp = GPIOx->LCKR;
/* Read LCKK bit*/
tmp = GPIOx->LCKR;
}
/**
* @brief Selects the GPIO pin used as Event output.
* @param GPIO_PortSource: selects the GPIO port to be used as source
* for Event output.
* This parameter can be GPIO_PortSourceGPIOx where x can be (A..E).
* @param GPIO_PinSource: specifies the pin for the Event output.
* This parameter can be GPIO_PinSourcex where x can be (0..15).
* @retval None
*/
void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
uint32_t tmpreg = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_EVENTOUT_PORT_SOURCE(GPIO_PortSource));
assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
tmpreg = AFIO->EVCR;
/* Clear the PORT[6:4] and PIN[3:0] bits */
tmpreg &= EVCR_PORTPINCONFIG_MASK;
tmpreg |= (uint32_t)GPIO_PortSource << 0x04;
tmpreg |= GPIO_PinSource;
AFIO->EVCR = tmpreg;
}
/**
* @brief Enables or disables the Event Output.
* @param NewState: new state of the Event output.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void GPIO_EventOutputCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) EVCR_EVOE_BB = (uint32_t)NewState;
}
/**
* @brief Changes the mapping of the specified pin.
* @param GPIO_Remap: selects the pin to remap.
* This parameter can be one of the following values:
* @arg GPIO_Remap_SPI1 : SPI1 Alternate Function mapping
* @arg GPIO_Remap_I2C1 : I2C1 Alternate Function mapping
* @arg GPIO_Remap_USART1 : USART1 Alternate Function mapping
* @arg GPIO_Remap_USART2 : USART2 Alternate Function mapping
* @arg GPIO_PartialRemap_USART3 : USART3 Partial Alternate Function mapping
* @arg GPIO_FullRemap_USART3 : USART3 Full Alternate Function mapping
* @arg GPIO_PartialRemap_TIM1 : TIM1 Partial Alternate Function mapping
* @arg GPIO_FullRemap_TIM1 : TIM1 Full Alternate Function mapping
* @arg GPIO_PartialRemap1_TIM2 : TIM2 Partial1 Alternate Function mapping
* @arg GPIO_PartialRemap2_TIM2 : TIM2 Partial2 Alternate Function mapping
* @arg GPIO_FullRemap_TIM2 : TIM2 Full Alternate Function mapping
* @arg GPIO_PartialRemap_TIM3 : TIM3 Partial Alternate Function mapping
* @arg GPIO_FullRemap_TIM3 : TIM3 Full Alternate Function mapping
* @arg GPIO_Remap_TIM4 : TIM4 Alternate Function mapping
* @arg GPIO_Remap1_CAN1 : CAN1 Alternate Function mapping
* @arg GPIO_Remap2_CAN1 : CAN1 Alternate Function mapping
* @arg GPIO_Remap_PD01 : PD01 Alternate Function mapping
* @arg GPIO_Remap_TIM5CH4_LSI : LSI connected to TIM5 Channel4 input capture for calibration
* @arg GPIO_Remap_ADC1_ETRGINJ : ADC1 External Trigger Injected Conversion remapping
* @arg GPIO_Remap_ADC1_ETRGREG : ADC1 External Trigger Regular Conversion remapping
* @arg GPIO_Remap_ADC2_ETRGINJ : ADC2 External Trigger Injected Conversion remapping
* @arg GPIO_Remap_ADC2_ETRGREG : ADC2 External Trigger Regular Conversion remapping
* @arg GPIO_Remap_ETH : Ethernet remapping (only for Connectivity line devices)
* @arg GPIO_Remap_CAN2 : CAN2 remapping (only for Connectivity line devices)
* @arg GPIO_Remap_SWJ_NoJTRST : Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST
* @arg GPIO_Remap_SWJ_JTAGDisable : JTAG-DP Disabled and SW-DP Enabled
* @arg GPIO_Remap_SWJ_Disable : Full SWJ Disabled (JTAG-DP + SW-DP)
* @arg GPIO_Remap_SPI3 : SPI3/I2S3 Alternate Function mapping (only for Connectivity line devices)
* When the SPI3/I2S3 is remapped using this function, the SWJ is configured
* to Full SWJ Enabled (JTAG-DP + SW-DP) but without JTRST.
* @arg GPIO_Remap_TIM2ITR1_PTP_SOF : Ethernet PTP output or USB OTG SOF (Start of Frame) connected
* to TIM2 Internal Trigger 1 for calibration (only for Connectivity line devices)
* If the GPIO_Remap_TIM2ITR1_PTP_SOF is enabled the TIM2 ITR1 is connected to
* Ethernet PTP output. When Reset TIM2 ITR1 is connected to USB OTG SOF output.
* @arg GPIO_Remap_PTP_PPS : Ethernet MAC PPS_PTS output on PB05 (only for Connectivity line devices)
* @arg GPIO_Remap_TIM15 : TIM15 Alternate Function mapping (only for Value line devices)
* @arg GPIO_Remap_TIM16 : TIM16 Alternate Function mapping (only for Value line devices)
* @arg GPIO_Remap_TIM17 : TIM17 Alternate Function mapping (only for Value line devices)
* @arg GPIO_Remap_CEC : CEC Alternate Function mapping (only for Value line devices)
* @arg GPIO_Remap_TIM1_DMA : TIM1 DMA requests mapping (only for Value line devices)
* @arg GPIO_Remap_TIM9 : TIM9 Alternate Function mapping (only for XL-density devices)
* @arg GPIO_Remap_TIM10 : TIM10 Alternate Function mapping (only for XL-density devices)
* @arg GPIO_Remap_TIM11 : TIM11 Alternate Function mapping (only for XL-density devices)
* @arg GPIO_Remap_TIM13 : TIM13 Alternate Function mapping (only for High density Value line and XL-density devices)
* @arg GPIO_Remap_TIM14 : TIM14 Alternate Function mapping (only for High density Value line and XL-density devices)
* @arg GPIO_Remap_FSMC_NADV : FSMC_NADV Alternate Function mapping (only for High density Value line and XL-density devices)
* @arg GPIO_Remap_TIM67_DAC_DMA : TIM6/TIM7 and DAC DMA requests remapping (only for High density Value line devices)
* @arg GPIO_Remap_TIM12 : TIM12 Alternate Function mapping (only for High density Value line devices)
* @arg GPIO_Remap_MISC : Miscellaneous Remap (DMA2 Channel5 Position and DAC Trigger remapping,
* only for High density Value line devices)
* @param NewState: new state of the port pin remapping.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)
{
uint32_t tmp = 0x00, tmp1 = 0x00, tmpreg = 0x00, tmpmask = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_REMAP(GPIO_Remap));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if((GPIO_Remap & 0x80000000) == 0x80000000)
{
tmpreg = AFIO->MAPR2;
}
else
{
tmpreg = AFIO->MAPR;
}
tmpmask = (GPIO_Remap & DBGAFR_POSITION_MASK) >> 0x10;
tmp = GPIO_Remap & LSB_MASK;
if ((GPIO_Remap & (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK)) == (DBGAFR_LOCATION_MASK | DBGAFR_NUMBITS_MASK))
{
tmpreg &= DBGAFR_SWJCFG_MASK;
AFIO->MAPR &= DBGAFR_SWJCFG_MASK;
}
else if ((GPIO_Remap & DBGAFR_NUMBITS_MASK) == DBGAFR_NUMBITS_MASK)
{
tmp1 = ((uint32_t)0x03) << tmpmask;
tmpreg &= ~tmp1;
tmpreg |= ~DBGAFR_SWJCFG_MASK;
}
else
{
tmpreg &= ~(tmp << ((GPIO_Remap >> 0x15)*0x10));
tmpreg |= ~DBGAFR_SWJCFG_MASK;
}
if (NewState != DISABLE)
{
tmpreg |= (tmp << ((GPIO_Remap >> 0x15)*0x10));
}
if((GPIO_Remap & 0x80000000) == 0x80000000)
{
AFIO->MAPR2 = tmpreg;
}
else
{
AFIO->MAPR = tmpreg;
}
}
/**
* @brief Selects the GPIO pin used as EXTI Line.
* @param GPIO_PortSource: selects the GPIO port to be used as source for EXTI lines.
* This parameter can be GPIO_PortSourceGPIOx where x can be (A..G).
* @param GPIO_PinSource: specifies the EXTI line to be configured.
* This parameter can be GPIO_PinSourcex where x can be (0..15).
* @retval None
*/
void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)
{
uint32_t tmp = 0x00;
/* Check the parameters */
assert_param(IS_GPIO_EXTI_PORT_SOURCE(GPIO_PortSource));
assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource));
tmp = ((uint32_t)0x0F) << (0x04 * (GPIO_PinSource & (uint8_t)0x03));
AFIO->EXTICR[GPIO_PinSource >> 0x02] &= ~tmp;
AFIO->EXTICR[GPIO_PinSource >> 0x02] |= (((uint32_t)GPIO_PortSource) << (0x04 * (GPIO_PinSource & (uint8_t)0x03)));
}
/**
* @brief Selects the Ethernet media interface.
* @note This function applies only to STM32 Connectivity line devices.
* @param GPIO_ETH_MediaInterface: specifies the Media Interface mode.
* This parameter can be one of the following values:
* @arg GPIO_ETH_MediaInterface_MII: MII mode
* @arg GPIO_ETH_MediaInterface_RMII: RMII mode
* @retval None
*/
void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface)
{
assert_param(IS_GPIO_ETH_MEDIA_INTERFACE(GPIO_ETH_MediaInterface));
/* Configure MII_RMII selection bit */
*(__IO uint32_t *) MAPR_MII_RMII_SEL_BB = GPIO_ETH_MediaInterface;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_i2c.c
================================================
/**
******************************************************************************
* @file stm32f10x_i2c.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the I2C firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_i2c.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup I2C
* @brief I2C driver modules
* @{
*/
/** @defgroup I2C_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup I2C_Private_Defines
* @{
*/
/* I2C SPE mask */
#define CR1_PE_Set ((uint16_t)0x0001)
#define CR1_PE_Reset ((uint16_t)0xFFFE)
/* I2C START mask */
#define CR1_START_Set ((uint16_t)0x0100)
#define CR1_START_Reset ((uint16_t)0xFEFF)
/* I2C STOP mask */
#define CR1_STOP_Set ((uint16_t)0x0200)
#define CR1_STOP_Reset ((uint16_t)0xFDFF)
/* I2C ACK mask */
#define CR1_ACK_Set ((uint16_t)0x0400)
#define CR1_ACK_Reset ((uint16_t)0xFBFF)
/* I2C ENGC mask */
#define CR1_ENGC_Set ((uint16_t)0x0040)
#define CR1_ENGC_Reset ((uint16_t)0xFFBF)
/* I2C SWRST mask */
#define CR1_SWRST_Set ((uint16_t)0x8000)
#define CR1_SWRST_Reset ((uint16_t)0x7FFF)
/* I2C PEC mask */
#define CR1_PEC_Set ((uint16_t)0x1000)
#define CR1_PEC_Reset ((uint16_t)0xEFFF)
/* I2C ENPEC mask */
#define CR1_ENPEC_Set ((uint16_t)0x0020)
#define CR1_ENPEC_Reset ((uint16_t)0xFFDF)
/* I2C ENARP mask */
#define CR1_ENARP_Set ((uint16_t)0x0010)
#define CR1_ENARP_Reset ((uint16_t)0xFFEF)
/* I2C NOSTRETCH mask */
#define CR1_NOSTRETCH_Set ((uint16_t)0x0080)
#define CR1_NOSTRETCH_Reset ((uint16_t)0xFF7F)
/* I2C registers Masks */
#define CR1_CLEAR_Mask ((uint16_t)0xFBF5)
/* I2C DMAEN mask */
#define CR2_DMAEN_Set ((uint16_t)0x0800)
#define CR2_DMAEN_Reset ((uint16_t)0xF7FF)
/* I2C LAST mask */
#define CR2_LAST_Set ((uint16_t)0x1000)
#define CR2_LAST_Reset ((uint16_t)0xEFFF)
/* I2C FREQ mask */
#define CR2_FREQ_Reset ((uint16_t)0xFFC0)
/* I2C ADD0 mask */
#define OAR1_ADD0_Set ((uint16_t)0x0001)
#define OAR1_ADD0_Reset ((uint16_t)0xFFFE)
/* I2C ENDUAL mask */
#define OAR2_ENDUAL_Set ((uint16_t)0x0001)
#define OAR2_ENDUAL_Reset ((uint16_t)0xFFFE)
/* I2C ADD2 mask */
#define OAR2_ADD2_Reset ((uint16_t)0xFF01)
/* I2C F/S mask */
#define CCR_FS_Set ((uint16_t)0x8000)
/* I2C CCR mask */
#define CCR_CCR_Set ((uint16_t)0x0FFF)
/* I2C FLAG mask */
#define FLAG_Mask ((uint32_t)0x00FFFFFF)
/* I2C Interrupt Enable mask */
#define ITEN_Mask ((uint32_t)0x07000000)
/**
* @}
*/
/** @defgroup I2C_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup I2C_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup I2C_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup I2C_Private_Functions
* @{
*/
/**
* @brief Deinitializes the I2Cx peripheral registers to their default reset values.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @retval None
*/
void I2C_DeInit(I2C_TypeDef* I2Cx)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
if (I2Cx == I2C1)
{
/* Enable I2C1 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);
/* Release I2C1 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);
}
else
{
/* Enable I2C2 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
/* Release I2C2 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);
}
}
/**
* @brief Initializes the I2Cx peripheral according to the specified
* parameters in the I2C_InitStruct.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_InitStruct: pointer to a I2C_InitTypeDef structure that
* contains the configuration information for the specified I2C peripheral.
* @retval None
*/
void I2C_Init(I2C_TypeDef* I2Cx, I2C_InitTypeDef* I2C_InitStruct)
{
uint16_t tmpreg = 0, freqrange = 0;
uint16_t result = 0x04;
uint32_t pclk1 = 8000000;
RCC_ClocksTypeDef rcc_clocks;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_CLOCK_SPEED(I2C_InitStruct->I2C_ClockSpeed));
assert_param(IS_I2C_MODE(I2C_InitStruct->I2C_Mode));
assert_param(IS_I2C_DUTY_CYCLE(I2C_InitStruct->I2C_DutyCycle));
assert_param(IS_I2C_OWN_ADDRESS1(I2C_InitStruct->I2C_OwnAddress1));
assert_param(IS_I2C_ACK_STATE(I2C_InitStruct->I2C_Ack));
assert_param(IS_I2C_ACKNOWLEDGE_ADDRESS(I2C_InitStruct->I2C_AcknowledgedAddress));
/*---------------------------- I2Cx CR2 Configuration ------------------------*/
/* Get the I2Cx CR2 value */
tmpreg = I2Cx->CR2;
/* Clear frequency FREQ[5:0] bits */
tmpreg &= CR2_FREQ_Reset;
/* Get pclk1 frequency value */
RCC_GetClocksFreq(&rcc_clocks);
pclk1 = rcc_clocks.PCLK1_Frequency;
/* Set frequency bits depending on pclk1 value */
freqrange = (uint16_t)(pclk1 / 1000000);
tmpreg |= freqrange;
/* Write to I2Cx CR2 */
I2Cx->CR2 = tmpreg;
/*---------------------------- I2Cx CCR Configuration ------------------------*/
/* Disable the selected I2C peripheral to configure TRISE */
I2Cx->CR1 &= CR1_PE_Reset;
/* Reset tmpreg value */
/* Clear F/S, DUTY and CCR[11:0] bits */
tmpreg = 0;
/* Configure speed in standard mode */
if (I2C_InitStruct->I2C_ClockSpeed <= 100000)
{
/* Standard mode speed calculate */
result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed << 1));
/* Test if CCR value is under 0x4*/
if (result < 0x04)
{
/* Set minimum allowed value */
result = 0x04;
}
/* Set speed value for standard mode */
tmpreg |= result;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/* Set Maximum Rise Time for standard mode */
I2Cx->TRISE = freqrange + 1;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
}
/* Configure speed in fast mode */
else /*(I2C_InitStruct->I2C_ClockSpeed <= 400000)*/
{
if (I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_2)
{
/* Fast mode speed calculate: Tlow/Thigh = 2 */
result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 3));
}
else /*I2C_InitStruct->I2C_DutyCycle == I2C_DutyCycle_16_9*/
{
/* Fast mode speed calculate: Tlow/Thigh = 16/9 */
result = (uint16_t)(pclk1 / (I2C_InitStruct->I2C_ClockSpeed * 25));
/* Set DUTY bit */
result |= I2C_DutyCycle_16_9;
}
/* Test if CCR value is under 0x1*/
if ((result & CCR_CCR_Set) == 0)
{
/* Set minimum allowed value */
result |= (uint16_t)0x0001;
}
/* Set speed value and set F/S bit for fast mode */
tmpreg |= (uint16_t)(result | CCR_FS_Set);
/* Set Maximum Rise Time for fast mode */
I2Cx->TRISE = (uint16_t)(((freqrange * (uint16_t)300) / (uint16_t)1000) + (uint16_t)1);
}
/* Write to I2Cx CCR */
I2Cx->CCR = tmpreg;
/* Enable the selected I2C peripheral */
I2Cx->CR1 |= CR1_PE_Set;
/*---------------------------- I2Cx CR1 Configuration ------------------------*/
/* Get the I2Cx CR1 value */
tmpreg = I2Cx->CR1;
/* Clear ACK, SMBTYPE and SMBUS bits */
tmpreg &= CR1_CLEAR_Mask;
/* Configure I2Cx: mode and acknowledgement */
/* Set SMBTYPE and SMBUS bits according to I2C_Mode value */
/* Set ACK bit according to I2C_Ack value */
tmpreg |= (uint16_t)((uint32_t)I2C_InitStruct->I2C_Mode | I2C_InitStruct->I2C_Ack);
/* Write to I2Cx CR1 */
I2Cx->CR1 = tmpreg;
/*---------------------------- I2Cx OAR1 Configuration -----------------------*/
/* Set I2Cx Own Address1 and acknowledged address */
I2Cx->OAR1 = (I2C_InitStruct->I2C_AcknowledgedAddress | I2C_InitStruct->I2C_OwnAddress1);
}
/**
* @brief Fills each I2C_InitStruct member with its default value.
* @param I2C_InitStruct: pointer to an I2C_InitTypeDef structure which will be initialized.
* @retval None
*/
void I2C_StructInit(I2C_InitTypeDef* I2C_InitStruct)
{
/*---------------- Reset I2C init structure parameters values ----------------*/
/* initialize the I2C_ClockSpeed member */
I2C_InitStruct->I2C_ClockSpeed = 5000;
/* Initialize the I2C_Mode member */
I2C_InitStruct->I2C_Mode = I2C_Mode_I2C;
/* Initialize the I2C_DutyCycle member */
I2C_InitStruct->I2C_DutyCycle = I2C_DutyCycle_2;
/* Initialize the I2C_OwnAddress1 member */
I2C_InitStruct->I2C_OwnAddress1 = 0;
/* Initialize the I2C_Ack member */
I2C_InitStruct->I2C_Ack = I2C_Ack_Disable;
/* Initialize the I2C_AcknowledgedAddress member */
I2C_InitStruct->I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
}
/**
* @brief Enables or disables the specified I2C peripheral.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2Cx peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_Cmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected I2C peripheral */
I2Cx->CR1 |= CR1_PE_Set;
}
else
{
/* Disable the selected I2C peripheral */
I2Cx->CR1 &= CR1_PE_Reset;
}
}
/**
* @brief Enables or disables the specified I2C DMA requests.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C DMA transfer.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_DMACmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected I2C DMA requests */
I2Cx->CR2 |= CR2_DMAEN_Set;
}
else
{
/* Disable the selected I2C DMA requests */
I2Cx->CR2 &= CR2_DMAEN_Reset;
}
}
/**
* @brief Specifies if the next DMA transfer will be the last one.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C DMA last transfer.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_DMALastTransferCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Next DMA transfer is the last transfer */
I2Cx->CR2 |= CR2_LAST_Set;
}
else
{
/* Next DMA transfer is not the last transfer */
I2Cx->CR2 &= CR2_LAST_Reset;
}
}
/**
* @brief Generates I2Cx communication START condition.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C START condition generation.
* This parameter can be: ENABLE or DISABLE.
* @retval None.
*/
void I2C_GenerateSTART(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Generate a START condition */
I2Cx->CR1 |= CR1_START_Set;
}
else
{
/* Disable the START condition generation */
I2Cx->CR1 &= CR1_START_Reset;
}
}
/**
* @brief Generates I2Cx communication STOP condition.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C STOP condition generation.
* This parameter can be: ENABLE or DISABLE.
* @retval None.
*/
void I2C_GenerateSTOP(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Generate a STOP condition */
I2Cx->CR1 |= CR1_STOP_Set;
}
else
{
/* Disable the STOP condition generation */
I2Cx->CR1 &= CR1_STOP_Reset;
}
}
/**
* @brief Enables or disables the specified I2C acknowledge feature.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C Acknowledgement.
* This parameter can be: ENABLE or DISABLE.
* @retval None.
*/
void I2C_AcknowledgeConfig(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the acknowledgement */
I2Cx->CR1 |= CR1_ACK_Set;
}
else
{
/* Disable the acknowledgement */
I2Cx->CR1 &= CR1_ACK_Reset;
}
}
/**
* @brief Configures the specified I2C own address2.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param Address: specifies the 7bit I2C own address2.
* @retval None.
*/
void I2C_OwnAddress2Config(I2C_TypeDef* I2Cx, uint8_t Address)
{
uint16_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
/* Get the old register value */
tmpreg = I2Cx->OAR2;
/* Reset I2Cx Own address2 bit [7:1] */
tmpreg &= OAR2_ADD2_Reset;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/* Set I2Cx Own address2 */
tmpreg |= (uint16_t)((uint16_t)Address & (uint16_t)0x00FE);
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/* Store the new register value */
I2Cx->OAR2 = tmpreg;
}
/**
* @brief Enables or disables the specified I2C dual addressing mode.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C dual addressing mode.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_DualAddressCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable dual addressing mode */
I2Cx->OAR2 |= OAR2_ENDUAL_Set;
}
else
{
/* Disable dual addressing mode */
I2Cx->OAR2 &= OAR2_ENDUAL_Reset;
}
}
/**
* @brief Enables or disables the specified I2C general call feature.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C General call.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_GeneralCallCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable generall call */
I2Cx->CR1 |= CR1_ENGC_Set;
}
else
{
/* Disable generall call */
I2Cx->CR1 &= CR1_ENGC_Reset;
}
}
/**
* @brief Enables or disables the specified I2C interrupts.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_IT: specifies the I2C interrupts sources to be enabled or disabled.
* This parameter can be any combination of the following values:
* @arg I2C_IT_BUF: Buffer interrupt mask
* @arg I2C_IT_EVT: Event interrupt mask
* @arg I2C_IT_ERR: Error interrupt mask
* @param NewState: new state of the specified I2C interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_ITConfig(I2C_TypeDef* I2Cx, uint16_t I2C_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
assert_param(IS_I2C_CONFIG_IT(I2C_IT));
if (NewState != DISABLE)
{
/* Enable the selected I2C interrupts */
I2Cx->CR2 |= I2C_IT;
}
else
{
/* Disable the selected I2C interrupts */
I2Cx->CR2 &= (uint16_t)~I2C_IT;
}
}
/**
* @brief Sends a data byte through the I2Cx peripheral.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param Data: Byte to be transmitted..
* @retval None
*/
void I2C_SendData(I2C_TypeDef* I2Cx, uint8_t Data)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
/* Write in the DR register the data to be sent */
I2Cx->DR = Data;
}
/**
* @brief Returns the most recent received data by the I2Cx peripheral.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @retval The value of the received data.
*/
uint8_t I2C_ReceiveData(I2C_TypeDef* I2Cx)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
/* Return the data in the DR register */
return (uint8_t)I2Cx->DR;
}
/**
* @brief Transmits the address byte to select the slave device.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param Address: specifies the slave address which will be transmitted
* @param I2C_Direction: specifies whether the I2C device will be a
* Transmitter or a Receiver. This parameter can be one of the following values
* @arg I2C_Direction_Transmitter: Transmitter mode
* @arg I2C_Direction_Receiver: Receiver mode
* @retval None.
*/
void I2C_Send7bitAddress(I2C_TypeDef* I2Cx, uint8_t Address, uint8_t I2C_Direction)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_DIRECTION(I2C_Direction));
/* Test on the direction to set/reset the read/write bit */
if (I2C_Direction != I2C_Direction_Transmitter)
{
/* Set the address bit0 for read */
Address |= OAR1_ADD0_Set;
}
else
{
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/* Reset the address bit0 for write */
Address &= OAR1_ADD0_Reset;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
}
/* Send the address */
I2Cx->DR = Address;
}
/**
* @brief Reads the specified I2C register and returns its value.
* @param I2C_Register: specifies the register to read.
* This parameter can be one of the following values:
* @arg I2C_Register_CR1: CR1 register.
* @arg I2C_Register_CR2: CR2 register.
* @arg I2C_Register_OAR1: OAR1 register.
* @arg I2C_Register_OAR2: OAR2 register.
* @arg I2C_Register_DR: DR register.
* @arg I2C_Register_SR1: SR1 register.
* @arg I2C_Register_SR2: SR2 register.
* @arg I2C_Register_CCR: CCR register.
* @arg I2C_Register_TRISE: TRISE register.
* @retval The value of the read register.
*/
uint16_t I2C_ReadRegister(I2C_TypeDef* I2Cx, uint8_t I2C_Register)
{
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_REGISTER(I2C_Register));
tmp = (uint32_t) I2Cx;
tmp += I2C_Register;
/* Return the selected register value */
return (*(__IO uint16_t *) tmp);
}
/**
* @brief Enables or disables the specified I2C software reset.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C software reset.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_SoftwareResetCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Peripheral under reset */
I2Cx->CR1 |= CR1_SWRST_Set;
}
else
{
/* Peripheral not under reset */
I2Cx->CR1 &= CR1_SWRST_Reset;
}
}
/**
* @brief Selects the specified I2C NACK position in master receiver mode.
* This function is useful in I2C Master Receiver mode when the number
* of data to be received is equal to 2. In this case, this function
* should be called (with parameter I2C_NACKPosition_Next) before data
* reception starts,as described in the 2-byte reception procedure
* recommended in Reference Manual in Section: Master receiver.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_NACKPosition: specifies the NACK position.
* This parameter can be one of the following values:
* @arg I2C_NACKPosition_Next: indicates that the next byte will be the last
* received byte.
* @arg I2C_NACKPosition_Current: indicates that current byte is the last
* received byte.
*
* @note This function configures the same bit (POS) as I2C_PECPositionConfig()
* but is intended to be used in I2C mode while I2C_PECPositionConfig()
* is intended to used in SMBUS mode.
*
* @retval None
*/
void I2C_NACKPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_NACKPosition)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_NACK_POSITION(I2C_NACKPosition));
/* Check the input parameter */
if (I2C_NACKPosition == I2C_NACKPosition_Next)
{
/* Next byte in shift register is the last received byte */
I2Cx->CR1 |= I2C_NACKPosition_Next;
}
else
{
/* Current byte in shift register is the last received byte */
I2Cx->CR1 &= I2C_NACKPosition_Current;
}
}
/**
* @brief Drives the SMBusAlert pin high or low for the specified I2C.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_SMBusAlert: specifies SMBAlert pin level.
* This parameter can be one of the following values:
* @arg I2C_SMBusAlert_Low: SMBAlert pin driven low
* @arg I2C_SMBusAlert_High: SMBAlert pin driven high
* @retval None
*/
void I2C_SMBusAlertConfig(I2C_TypeDef* I2Cx, uint16_t I2C_SMBusAlert)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_SMBUS_ALERT(I2C_SMBusAlert));
if (I2C_SMBusAlert == I2C_SMBusAlert_Low)
{
/* Drive the SMBusAlert pin Low */
I2Cx->CR1 |= I2C_SMBusAlert_Low;
}
else
{
/* Drive the SMBusAlert pin High */
I2Cx->CR1 &= I2C_SMBusAlert_High;
}
}
/**
* @brief Enables or disables the specified I2C PEC transfer.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2C PEC transmission.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_TransmitPEC(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected I2C PEC transmission */
I2Cx->CR1 |= CR1_PEC_Set;
}
else
{
/* Disable the selected I2C PEC transmission */
I2Cx->CR1 &= CR1_PEC_Reset;
}
}
/**
* @brief Selects the specified I2C PEC position.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_PECPosition: specifies the PEC position.
* This parameter can be one of the following values:
* @arg I2C_PECPosition_Next: indicates that the next byte is PEC
* @arg I2C_PECPosition_Current: indicates that current byte is PEC
*
* @note This function configures the same bit (POS) as I2C_NACKPositionConfig()
* but is intended to be used in SMBUS mode while I2C_NACKPositionConfig()
* is intended to used in I2C mode.
*
* @retval None
*/
void I2C_PECPositionConfig(I2C_TypeDef* I2Cx, uint16_t I2C_PECPosition)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_PEC_POSITION(I2C_PECPosition));
if (I2C_PECPosition == I2C_PECPosition_Next)
{
/* Next byte in shift register is PEC */
I2Cx->CR1 |= I2C_PECPosition_Next;
}
else
{
/* Current byte in shift register is PEC */
I2Cx->CR1 &= I2C_PECPosition_Current;
}
}
/**
* @brief Enables or disables the PEC value calculation of the transferred bytes.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2Cx PEC value calculation.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_CalculatePEC(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected I2C PEC calculation */
I2Cx->CR1 |= CR1_ENPEC_Set;
}
else
{
/* Disable the selected I2C PEC calculation */
I2Cx->CR1 &= CR1_ENPEC_Reset;
}
}
/**
* @brief Returns the PEC value for the specified I2C.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @retval The PEC value.
*/
uint8_t I2C_GetPEC(I2C_TypeDef* I2Cx)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/* Return the selected I2C PEC value */
return ((I2Cx->SR2) >> 8);
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
}
/**
* @brief Enables or disables the specified I2C ARP.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2Cx ARP.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_ARPCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected I2C ARP */
I2Cx->CR1 |= CR1_ENARP_Set;
}
else
{
/* Disable the selected I2C ARP */
I2Cx->CR1 &= CR1_ENARP_Reset;
}
}
/**
* @brief Enables or disables the specified I2C Clock stretching.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param NewState: new state of the I2Cx Clock stretching.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2C_StretchClockCmd(I2C_TypeDef* I2Cx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState == DISABLE)
{
/* Enable the selected I2C Clock stretching */
I2Cx->CR1 |= CR1_NOSTRETCH_Set;
}
else
{
/* Disable the selected I2C Clock stretching */
I2Cx->CR1 &= CR1_NOSTRETCH_Reset;
}
}
/**
* @brief Selects the specified I2C fast mode duty cycle.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_DutyCycle: specifies the fast mode duty cycle.
* This parameter can be one of the following values:
* @arg I2C_DutyCycle_2: I2C fast mode Tlow/Thigh = 2
* @arg I2C_DutyCycle_16_9: I2C fast mode Tlow/Thigh = 16/9
* @retval None
*/
void I2C_FastModeDutyCycleConfig(I2C_TypeDef* I2Cx, uint16_t I2C_DutyCycle)
{
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_DUTY_CYCLE(I2C_DutyCycle));
if (I2C_DutyCycle != I2C_DutyCycle_16_9)
{
/* I2C fast mode Tlow/Thigh=2 */
I2Cx->CCR &= I2C_DutyCycle_2;
}
else
{
/* I2C fast mode Tlow/Thigh=16/9 */
I2Cx->CCR |= I2C_DutyCycle_16_9;
}
}
/**
* @brief
****************************************************************************************
*
* I2C State Monitoring Functions
*
****************************************************************************************
* This I2C driver provides three different ways for I2C state monitoring
* depending on the application requirements and constraints:
*
*
* 1) Basic state monitoring:
* Using I2C_CheckEvent() function:
* It compares the status registers (SR1 and SR2) content to a given event
* (can be the combination of one or more flags).
* It returns SUCCESS if the current status includes the given flags
* and returns ERROR if one or more flags are missing in the current status.
* - When to use:
* - This function is suitable for most applications as well as for startup
* activity since the events are fully described in the product reference manual
* (RM0008).
* - It is also suitable for users who need to define their own events.
* - Limitations:
* - If an error occurs (ie. error flags are set besides to the monitored flags),
* the I2C_CheckEvent() function may return SUCCESS despite the communication
* hold or corrupted real state.
* In this case, it is advised to use error interrupts to monitor the error
* events and handle them in the interrupt IRQ handler.
*
* @note
* For error management, it is advised to use the following functions:
* - I2C_ITConfig() to configure and enable the error interrupts (I2C_IT_ERR).
* - I2Cx_ER_IRQHandler() which is called when the error interrupt occurs.
* Where x is the peripheral instance (I2C1, I2C2 ...)
* - I2C_GetFlagStatus() or I2C_GetITStatus() to be called into I2Cx_ER_IRQHandler()
* in order to determine which error occured.
* - I2C_ClearFlag() or I2C_ClearITPendingBit() and/or I2C_SoftwareResetCmd()
* and/or I2C_GenerateStop() in order to clear the error flag and source,
* and return to correct communication status.
*
*
* 2) Advanced state monitoring:
* Using the function I2C_GetLastEvent() which returns the image of both status
* registers in a single word (uint32_t) (Status Register 2 value is shifted left
* by 16 bits and concatenated to Status Register 1).
* - When to use:
* - This function is suitable for the same applications above but it allows to
* overcome the mentioned limitation of I2C_GetFlagStatus() function.
* The returned value could be compared to events already defined in the
* library (stm32f10x_i2c.h) or to custom values defined by user.
* - This function is suitable when multiple flags are monitored at the same time.
* - At the opposite of I2C_CheckEvent() function, this function allows user to
* choose when an event is accepted (when all events flags are set and no
* other flags are set or just when the needed flags are set like
* I2C_CheckEvent() function).
* - Limitations:
* - User may need to define his own events.
* - Same remark concerning the error management is applicable for this
* function if user decides to check only regular communication flags (and
* ignores error flags).
*
*
* 3) Flag-based state monitoring:
* Using the function I2C_GetFlagStatus() which simply returns the status of
* one single flag (ie. I2C_FLAG_RXNE ...).
* - When to use:
* - This function could be used for specific applications or in debug phase.
* - It is suitable when only one flag checking is needed (most I2C events
* are monitored through multiple flags).
* - Limitations:
* - When calling this function, the Status register is accessed. Some flags are
* cleared when the status register is accessed. So checking the status
* of one Flag, may clear other ones.
* - Function may need to be called twice or more in order to monitor one
* single event.
*
* For detailed description of Events, please refer to section I2C_Events in
* stm32f10x_i2c.h file.
*
*/
/**
*
* 1) Basic state monitoring
*******************************************************************************
*/
/**
* @brief Checks whether the last I2Cx Event is equal to the one passed
* as parameter.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_EVENT: specifies the event to be checked.
* This parameter can be one of the following values:
* @arg I2C_EVENT_SLAVE_TRANSMITTER_ADDRESS_MATCHED : EV1
* @arg I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED : EV1
* @arg I2C_EVENT_SLAVE_TRANSMITTER_SECONDADDRESS_MATCHED : EV1
* @arg I2C_EVENT_SLAVE_RECEIVER_SECONDADDRESS_MATCHED : EV1
* @arg I2C_EVENT_SLAVE_GENERALCALLADDRESS_MATCHED : EV1
* @arg I2C_EVENT_SLAVE_BYTE_RECEIVED : EV2
* @arg (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_DUALF) : EV2
* @arg (I2C_EVENT_SLAVE_BYTE_RECEIVED | I2C_FLAG_GENCALL) : EV2
* @arg I2C_EVENT_SLAVE_BYTE_TRANSMITTED : EV3
* @arg (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_DUALF) : EV3
* @arg (I2C_EVENT_SLAVE_BYTE_TRANSMITTED | I2C_FLAG_GENCALL) : EV3
* @arg I2C_EVENT_SLAVE_ACK_FAILURE : EV3_2
* @arg I2C_EVENT_SLAVE_STOP_DETECTED : EV4
* @arg I2C_EVENT_MASTER_MODE_SELECT : EV5
* @arg I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED : EV6
* @arg I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED : EV6
* @arg I2C_EVENT_MASTER_BYTE_RECEIVED : EV7
* @arg I2C_EVENT_MASTER_BYTE_TRANSMITTING : EV8
* @arg I2C_EVENT_MASTER_BYTE_TRANSMITTED : EV8_2
* @arg I2C_EVENT_MASTER_MODE_ADDRESS10 : EV9
*
* @note: For detailed description of Events, please refer to section
* I2C_Events in stm32f10x_i2c.h file.
*
* @retval An ErrorStatus enumeration value:
* - SUCCESS: Last event is equal to the I2C_EVENT
* - ERROR: Last event is different from the I2C_EVENT
*/
ErrorStatus I2C_CheckEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
uint32_t lastevent = 0;
uint32_t flag1 = 0, flag2 = 0;
ErrorStatus status = ERROR;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_EVENT(I2C_EVENT));
/* Read the I2Cx status register */
flag1 = I2Cx->SR1;
flag2 = I2Cx->SR2;
flag2 = flag2 << 16;
/* Get the last event value from I2C status register */
lastevent = (flag1 | flag2) & FLAG_Mask;
/* Check whether the last event contains the I2C_EVENT */
if ((lastevent & I2C_EVENT) == I2C_EVENT)
{
/* SUCCESS: last event is equal to I2C_EVENT */
status = SUCCESS;
}
else
{
/* ERROR: last event is different from I2C_EVENT */
status = ERROR;
}
/* Return status */
return status;
}
/**
*
* 2) Advanced state monitoring
*******************************************************************************
*/
/**
* @brief Returns the last I2Cx Event.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
*
* @note: For detailed description of Events, please refer to section
* I2C_Events in stm32f10x_i2c.h file.
*
* @retval The last event
*/
uint32_t I2C_GetLastEvent(I2C_TypeDef* I2Cx)
{
uint32_t lastevent = 0;
uint32_t flag1 = 0, flag2 = 0;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
/* Read the I2Cx status register */
flag1 = I2Cx->SR1;
flag2 = I2Cx->SR2;
flag2 = flag2 << 16;
/* Get the last event value from I2C status register */
lastevent = (flag1 | flag2) & FLAG_Mask;
/* Return status */
return lastevent;
}
/**
*
* 3) Flag-based state monitoring
*******************************************************************************
*/
/**
* @brief Checks whether the specified I2C flag is set or not.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_FLAG: specifies the flag to check.
* This parameter can be one of the following values:
* @arg I2C_FLAG_DUALF: Dual flag (Slave mode)
* @arg I2C_FLAG_SMBHOST: SMBus host header (Slave mode)
* @arg I2C_FLAG_SMBDEFAULT: SMBus default header (Slave mode)
* @arg I2C_FLAG_GENCALL: General call header flag (Slave mode)
* @arg I2C_FLAG_TRA: Transmitter/Receiver flag
* @arg I2C_FLAG_BUSY: Bus busy flag
* @arg I2C_FLAG_MSL: Master/Slave flag
* @arg I2C_FLAG_SMBALERT: SMBus Alert flag
* @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag
* @arg I2C_FLAG_PECERR: PEC error in reception flag
* @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode)
* @arg I2C_FLAG_AF: Acknowledge failure flag
* @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode)
* @arg I2C_FLAG_BERR: Bus error flag
* @arg I2C_FLAG_TXE: Data register empty flag (Transmitter)
* @arg I2C_FLAG_RXNE: Data register not empty (Receiver) flag
* @arg I2C_FLAG_STOPF: Stop detection flag (Slave mode)
* @arg I2C_FLAG_ADD10: 10-bit header sent flag (Master mode)
* @arg I2C_FLAG_BTF: Byte transfer finished flag
* @arg I2C_FLAG_ADDR: Address sent flag (Master mode) "ADSL"
* Address matched flag (Slave mode)"ENDA"
* @arg I2C_FLAG_SB: Start bit flag (Master mode)
* @retval The new state of I2C_FLAG (SET or RESET).
*/
FlagStatus I2C_GetFlagStatus(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG)
{
FlagStatus bitstatus = RESET;
__IO uint32_t i2creg = 0, i2cxbase = 0;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_GET_FLAG(I2C_FLAG));
/* Get the I2Cx peripheral base address */
i2cxbase = (uint32_t)I2Cx;
/* Read flag register index */
i2creg = I2C_FLAG >> 28;
/* Get bit[23:0] of the flag */
I2C_FLAG &= FLAG_Mask;
if(i2creg != 0)
{
/* Get the I2Cx SR1 register address */
i2cxbase += 0x14;
}
else
{
/* Flag in I2Cx SR2 Register */
I2C_FLAG = (uint32_t)(I2C_FLAG >> 16);
/* Get the I2Cx SR2 register address */
i2cxbase += 0x18;
}
if(((*(__IO uint32_t *)i2cxbase) & I2C_FLAG) != (uint32_t)RESET)
{
/* I2C_FLAG is set */
bitstatus = SET;
}
else
{
/* I2C_FLAG is reset */
bitstatus = RESET;
}
/* Return the I2C_FLAG status */
return bitstatus;
}
/**
* @brief Clears the I2Cx's pending flags.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_FLAG: specifies the flag to clear.
* This parameter can be any combination of the following values:
* @arg I2C_FLAG_SMBALERT: SMBus Alert flag
* @arg I2C_FLAG_TIMEOUT: Timeout or Tlow error flag
* @arg I2C_FLAG_PECERR: PEC error in reception flag
* @arg I2C_FLAG_OVR: Overrun/Underrun flag (Slave mode)
* @arg I2C_FLAG_AF: Acknowledge failure flag
* @arg I2C_FLAG_ARLO: Arbitration lost flag (Master mode)
* @arg I2C_FLAG_BERR: Bus error flag
*
* @note
* - STOPF (STOP detection) is cleared by software sequence: a read operation
* to I2C_SR1 register (I2C_GetFlagStatus()) followed by a write operation
* to I2C_CR1 register (I2C_Cmd() to re-enable the I2C peripheral).
* - ADD10 (10-bit header sent) is cleared by software sequence: a read
* operation to I2C_SR1 (I2C_GetFlagStatus()) followed by writing the
* second byte of the address in DR register.
* - BTF (Byte Transfer Finished) is cleared by software sequence: a read
* operation to I2C_SR1 register (I2C_GetFlagStatus()) followed by a
* read/write to I2C_DR register (I2C_SendData()).
* - ADDR (Address sent) is cleared by software sequence: a read operation to
* I2C_SR1 register (I2C_GetFlagStatus()) followed by a read operation to
* I2C_SR2 register ((void)(I2Cx->SR2)).
* - SB (Start Bit) is cleared software sequence: a read operation to I2C_SR1
* register (I2C_GetFlagStatus()) followed by a write operation to I2C_DR
* register (I2C_SendData()).
* @retval None
*/
void I2C_ClearFlag(I2C_TypeDef* I2Cx, uint32_t I2C_FLAG)
{
uint32_t flagpos = 0;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_CLEAR_FLAG(I2C_FLAG));
/* Get the I2C flag position */
flagpos = I2C_FLAG & FLAG_Mask;
/* Clear the selected I2C flag */
I2Cx->SR1 = (uint16_t)~flagpos;
}
/**
* @brief Checks whether the specified I2C interrupt has occurred or not.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_IT: specifies the interrupt source to check.
* This parameter can be one of the following values:
* @arg I2C_IT_SMBALERT: SMBus Alert flag
* @arg I2C_IT_TIMEOUT: Timeout or Tlow error flag
* @arg I2C_IT_PECERR: PEC error in reception flag
* @arg I2C_IT_OVR: Overrun/Underrun flag (Slave mode)
* @arg I2C_IT_AF: Acknowledge failure flag
* @arg I2C_IT_ARLO: Arbitration lost flag (Master mode)
* @arg I2C_IT_BERR: Bus error flag
* @arg I2C_IT_TXE: Data register empty flag (Transmitter)
* @arg I2C_IT_RXNE: Data register not empty (Receiver) flag
* @arg I2C_IT_STOPF: Stop detection flag (Slave mode)
* @arg I2C_IT_ADD10: 10-bit header sent flag (Master mode)
* @arg I2C_IT_BTF: Byte transfer finished flag
* @arg I2C_IT_ADDR: Address sent flag (Master mode) "ADSL"
* Address matched flag (Slave mode)"ENDAD"
* @arg I2C_IT_SB: Start bit flag (Master mode)
* @retval The new state of I2C_IT (SET or RESET).
*/
ITStatus I2C_GetITStatus(I2C_TypeDef* I2Cx, uint32_t I2C_IT)
{
ITStatus bitstatus = RESET;
uint32_t enablestatus = 0;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_GET_IT(I2C_IT));
/* Check if the interrupt source is enabled or not */
enablestatus = (uint32_t)(((I2C_IT & ITEN_Mask) >> 16) & (I2Cx->CR2)) ;
/* Get bit[23:0] of the flag */
I2C_IT &= FLAG_Mask;
/* Check the status of the specified I2C flag */
if (((I2Cx->SR1 & I2C_IT) != (uint32_t)RESET) && enablestatus)
{
/* I2C_IT is set */
bitstatus = SET;
}
else
{
/* I2C_IT is reset */
bitstatus = RESET;
}
/* Return the I2C_IT status */
return bitstatus;
}
/**
* @brief Clears the I2Cx�s interrupt pending bits.
* @param I2Cx: where x can be 1 or 2 to select the I2C peripheral.
* @param I2C_IT: specifies the interrupt pending bit to clear.
* This parameter can be any combination of the following values:
* @arg I2C_IT_SMBALERT: SMBus Alert interrupt
* @arg I2C_IT_TIMEOUT: Timeout or Tlow error interrupt
* @arg I2C_IT_PECERR: PEC error in reception interrupt
* @arg I2C_IT_OVR: Overrun/Underrun interrupt (Slave mode)
* @arg I2C_IT_AF: Acknowledge failure interrupt
* @arg I2C_IT_ARLO: Arbitration lost interrupt (Master mode)
* @arg I2C_IT_BERR: Bus error interrupt
*
* @note
* - STOPF (STOP detection) is cleared by software sequence: a read operation
* to I2C_SR1 register (I2C_GetITStatus()) followed by a write operation to
* I2C_CR1 register (I2C_Cmd() to re-enable the I2C peripheral).
* - ADD10 (10-bit header sent) is cleared by software sequence: a read
* operation to I2C_SR1 (I2C_GetITStatus()) followed by writing the second
* byte of the address in I2C_DR register.
* - BTF (Byte Transfer Finished) is cleared by software sequence: a read
* operation to I2C_SR1 register (I2C_GetITStatus()) followed by a
* read/write to I2C_DR register (I2C_SendData()).
* - ADDR (Address sent) is cleared by software sequence: a read operation to
* I2C_SR1 register (I2C_GetITStatus()) followed by a read operation to
* I2C_SR2 register ((void)(I2Cx->SR2)).
* - SB (Start Bit) is cleared by software sequence: a read operation to
* I2C_SR1 register (I2C_GetITStatus()) followed by a write operation to
* I2C_DR register (I2C_SendData()).
* @retval None
*/
void I2C_ClearITPendingBit(I2C_TypeDef* I2Cx, uint32_t I2C_IT)
{
uint32_t flagpos = 0;
/* Check the parameters */
assert_param(IS_I2C_ALL_PERIPH(I2Cx));
assert_param(IS_I2C_CLEAR_IT(I2C_IT));
/* Get the I2C flag position */
flagpos = I2C_IT & FLAG_Mask;
/* Clear the selected I2C flag */
I2Cx->SR1 = (uint16_t)~flagpos;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_iwdg.c
================================================
/**
******************************************************************************
* @file stm32f10x_iwdg.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the IWDG firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_iwdg.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup IWDG
* @brief IWDG driver modules
* @{
*/
/** @defgroup IWDG_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup IWDG_Private_Defines
* @{
*/
/* ---------------------- IWDG registers bit mask ----------------------------*/
/* KR register bit mask */
#define KR_KEY_Reload ((uint16_t)0xAAAA)
#define KR_KEY_Enable ((uint16_t)0xCCCC)
/**
* @}
*/
/** @defgroup IWDG_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup IWDG_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup IWDG_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup IWDG_Private_Functions
* @{
*/
/**
* @brief Enables or disables write access to IWDG_PR and IWDG_RLR registers.
* @param IWDG_WriteAccess: new state of write access to IWDG_PR and IWDG_RLR registers.
* This parameter can be one of the following values:
* @arg IWDG_WriteAccess_Enable: Enable write access to IWDG_PR and IWDG_RLR registers
* @arg IWDG_WriteAccess_Disable: Disable write access to IWDG_PR and IWDG_RLR registers
* @retval None
*/
void IWDG_WriteAccessCmd(uint16_t IWDG_WriteAccess)
{
/* Check the parameters */
assert_param(IS_IWDG_WRITE_ACCESS(IWDG_WriteAccess));
IWDG->KR = IWDG_WriteAccess;
}
/**
* @brief Sets IWDG Prescaler value.
* @param IWDG_Prescaler: specifies the IWDG Prescaler value.
* This parameter can be one of the following values:
* @arg IWDG_Prescaler_4: IWDG prescaler set to 4
* @arg IWDG_Prescaler_8: IWDG prescaler set to 8
* @arg IWDG_Prescaler_16: IWDG prescaler set to 16
* @arg IWDG_Prescaler_32: IWDG prescaler set to 32
* @arg IWDG_Prescaler_64: IWDG prescaler set to 64
* @arg IWDG_Prescaler_128: IWDG prescaler set to 128
* @arg IWDG_Prescaler_256: IWDG prescaler set to 256
* @retval None
*/
void IWDG_SetPrescaler(uint8_t IWDG_Prescaler)
{
/* Check the parameters */
assert_param(IS_IWDG_PRESCALER(IWDG_Prescaler));
IWDG->PR = IWDG_Prescaler;
}
/**
* @brief Sets IWDG Reload value.
* @param Reload: specifies the IWDG Reload value.
* This parameter must be a number between 0 and 0x0FFF.
* @retval None
*/
void IWDG_SetReload(uint16_t Reload)
{
/* Check the parameters */
assert_param(IS_IWDG_RELOAD(Reload));
IWDG->RLR = Reload;
}
/**
* @brief Reloads IWDG counter with value defined in the reload register
* (write access to IWDG_PR and IWDG_RLR registers disabled).
* @param None
* @retval None
*/
void IWDG_ReloadCounter(void)
{
IWDG->KR = KR_KEY_Reload;
}
/**
* @brief Enables IWDG (write access to IWDG_PR and IWDG_RLR registers disabled).
* @param None
* @retval None
*/
void IWDG_Enable(void)
{
IWDG->KR = KR_KEY_Enable;
}
/**
* @brief Checks whether the specified IWDG flag is set or not.
* @param IWDG_FLAG: specifies the flag to check.
* This parameter can be one of the following values:
* @arg IWDG_FLAG_PVU: Prescaler Value Update on going
* @arg IWDG_FLAG_RVU: Reload Value Update on going
* @retval The new state of IWDG_FLAG (SET or RESET).
*/
FlagStatus IWDG_GetFlagStatus(uint16_t IWDG_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_IWDG_FLAG(IWDG_FLAG));
if ((IWDG->SR & IWDG_FLAG) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
/* Return the flag status */
return bitstatus;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_pwr.c
================================================
/**
******************************************************************************
* @file stm32f10x_pwr.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the PWR firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_pwr.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup PWR
* @brief PWR driver modules
* @{
*/
/** @defgroup PWR_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup PWR_Private_Defines
* @{
*/
/* --------- PWR registers bit address in the alias region ---------- */
#define PWR_OFFSET (PWR_BASE - PERIPH_BASE)
/* --- CR Register ---*/
/* Alias word address of DBP bit */
#define CR_OFFSET (PWR_OFFSET + 0x00)
#define DBP_BitNumber 0x08
#define CR_DBP_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (DBP_BitNumber * 4))
/* Alias word address of PVDE bit */
#define PVDE_BitNumber 0x04
#define CR_PVDE_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PVDE_BitNumber * 4))
/* --- CSR Register ---*/
/* Alias word address of EWUP bit */
#define CSR_OFFSET (PWR_OFFSET + 0x04)
#define EWUP_BitNumber 0x08
#define CSR_EWUP_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (EWUP_BitNumber * 4))
/* ------------------ PWR registers bit mask ------------------------ */
/* CR register bit mask */
#define CR_DS_MASK ((uint32_t)0xFFFFFFFC)
#define CR_PLS_MASK ((uint32_t)0xFFFFFF1F)
/**
* @}
*/
/** @defgroup PWR_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup PWR_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup PWR_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup PWR_Private_Functions
* @{
*/
/**
* @brief Deinitializes the PWR peripheral registers to their default reset values.
* @param None
* @retval None
*/
void PWR_DeInit(void)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_PWR, DISABLE);
}
/**
* @brief Enables or disables access to the RTC and backup registers.
* @param NewState: new state of the access to the RTC and backup registers.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void PWR_BackupAccessCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CR_DBP_BB = (uint32_t)NewState;
}
/**
* @brief Enables or disables the Power Voltage Detector(PVD).
* @param NewState: new state of the PVD.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void PWR_PVDCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CR_PVDE_BB = (uint32_t)NewState;
}
/**
* @brief Configures the voltage threshold detected by the Power Voltage Detector(PVD).
* @param PWR_PVDLevel: specifies the PVD detection level
* This parameter can be one of the following values:
* @arg PWR_PVDLevel_2V2: PVD detection level set to 2.2V
* @arg PWR_PVDLevel_2V3: PVD detection level set to 2.3V
* @arg PWR_PVDLevel_2V4: PVD detection level set to 2.4V
* @arg PWR_PVDLevel_2V5: PVD detection level set to 2.5V
* @arg PWR_PVDLevel_2V6: PVD detection level set to 2.6V
* @arg PWR_PVDLevel_2V7: PVD detection level set to 2.7V
* @arg PWR_PVDLevel_2V8: PVD detection level set to 2.8V
* @arg PWR_PVDLevel_2V9: PVD detection level set to 2.9V
* @retval None
*/
void PWR_PVDLevelConfig(uint32_t PWR_PVDLevel)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_PWR_PVD_LEVEL(PWR_PVDLevel));
tmpreg = PWR->CR;
/* Clear PLS[7:5] bits */
tmpreg &= CR_PLS_MASK;
/* Set PLS[7:5] bits according to PWR_PVDLevel value */
tmpreg |= PWR_PVDLevel;
/* Store the new value */
PWR->CR = tmpreg;
}
/**
* @brief Enables or disables the WakeUp Pin functionality.
* @param NewState: new state of the WakeUp Pin functionality.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void PWR_WakeUpPinCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CSR_EWUP_BB = (uint32_t)NewState;
}
/**
* @brief Enters STOP mode.
* @param PWR_Regulator: specifies the regulator state in STOP mode.
* This parameter can be one of the following values:
* @arg PWR_Regulator_ON: STOP mode with regulator ON
* @arg PWR_Regulator_LowPower: STOP mode with regulator in low power mode
* @param PWR_STOPEntry: specifies if STOP mode in entered with WFI or WFE instruction.
* This parameter can be one of the following values:
* @arg PWR_STOPEntry_WFI: enter STOP mode with WFI instruction
* @arg PWR_STOPEntry_WFE: enter STOP mode with WFE instruction
* @retval None
*/
void PWR_EnterSTOPMode(uint32_t PWR_Regulator, uint8_t PWR_STOPEntry)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_PWR_REGULATOR(PWR_Regulator));
assert_param(IS_PWR_STOP_ENTRY(PWR_STOPEntry));
/* Select the regulator state in STOP mode ---------------------------------*/
tmpreg = PWR->CR;
/* Clear PDDS and LPDS bits */
tmpreg &= CR_DS_MASK;
/* Set LPDS bit according to PWR_Regulator value */
tmpreg |= PWR_Regulator;
/* Store the new value */
PWR->CR = tmpreg;
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* Select STOP mode entry --------------------------------------------------*/
if(PWR_STOPEntry == PWR_STOPEntry_WFI)
{
/* Request Wait For Interrupt */
__WFI();
}
else
{
/* Request Wait For Event */
__WFE();
}
/* Reset SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR &= (uint32_t)~((uint32_t)SCB_SCR_SLEEPDEEP);
}
/**
* @brief Enters STANDBY mode.
* @param None
* @retval None
*/
void PWR_EnterSTANDBYMode(void)
{
/* Clear Wake-up flag */
PWR->CR |= PWR_CR_CWUF;
/* Select STANDBY mode */
PWR->CR |= PWR_CR_PDDS;
/* Set SLEEPDEEP bit of Cortex System Control Register */
SCB->SCR |= SCB_SCR_SLEEPDEEP;
/* This option is used to ensure that store operations are completed */
#if defined ( __CC_ARM )
__force_stores();
#endif
/* Request Wait For Interrupt */
__WFI();
}
/**
* @brief Checks whether the specified PWR flag is set or not.
* @param PWR_FLAG: specifies the flag to check.
* This parameter can be one of the following values:
* @arg PWR_FLAG_WU: Wake Up flag
* @arg PWR_FLAG_SB: StandBy flag
* @arg PWR_FLAG_PVDO: PVD Output
* @retval The new state of PWR_FLAG (SET or RESET).
*/
FlagStatus PWR_GetFlagStatus(uint32_t PWR_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_PWR_GET_FLAG(PWR_FLAG));
if ((PWR->CSR & PWR_FLAG) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
/* Return the flag status */
return bitstatus;
}
/**
* @brief Clears the PWR's pending flags.
* @param PWR_FLAG: specifies the flag to clear.
* This parameter can be one of the following values:
* @arg PWR_FLAG_WU: Wake Up flag
* @arg PWR_FLAG_SB: StandBy flag
* @retval None
*/
void PWR_ClearFlag(uint32_t PWR_FLAG)
{
/* Check the parameters */
assert_param(IS_PWR_CLEAR_FLAG(PWR_FLAG));
PWR->CR |= PWR_FLAG << 2;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_rcc.c
================================================
/**
******************************************************************************
* @file stm32f10x_rcc.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the RCC firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup RCC
* @brief RCC driver modules
* @{
*/
/** @defgroup RCC_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup RCC_Private_Defines
* @{
*/
/* ------------ RCC registers bit address in the alias region ----------- */
#define RCC_OFFSET (RCC_BASE - PERIPH_BASE)
/* --- CR Register ---*/
/* Alias word address of HSION bit */
#define CR_OFFSET (RCC_OFFSET + 0x00)
#define HSION_BitNumber 0x00
#define CR_HSION_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (HSION_BitNumber * 4))
/* Alias word address of PLLON bit */
#define PLLON_BitNumber 0x18
#define CR_PLLON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLLON_BitNumber * 4))
#ifdef STM32F10X_CL
/* Alias word address of PLL2ON bit */
#define PLL2ON_BitNumber 0x1A
#define CR_PLL2ON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLL2ON_BitNumber * 4))
/* Alias word address of PLL3ON bit */
#define PLL3ON_BitNumber 0x1C
#define CR_PLL3ON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (PLL3ON_BitNumber * 4))
#endif /* STM32F10X_CL */
/* Alias word address of CSSON bit */
#define CSSON_BitNumber 0x13
#define CR_CSSON_BB (PERIPH_BB_BASE + (CR_OFFSET * 32) + (CSSON_BitNumber * 4))
/* --- CFGR Register ---*/
/* Alias word address of USBPRE bit */
#define CFGR_OFFSET (RCC_OFFSET + 0x04)
#ifndef STM32F10X_CL
#define USBPRE_BitNumber 0x16
#define CFGR_USBPRE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (USBPRE_BitNumber * 4))
#else
#define OTGFSPRE_BitNumber 0x16
#define CFGR_OTGFSPRE_BB (PERIPH_BB_BASE + (CFGR_OFFSET * 32) + (OTGFSPRE_BitNumber * 4))
#endif /* STM32F10X_CL */
/* --- BDCR Register ---*/
/* Alias word address of RTCEN bit */
#define BDCR_OFFSET (RCC_OFFSET + 0x20)
#define RTCEN_BitNumber 0x0F
#define BDCR_RTCEN_BB (PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (RTCEN_BitNumber * 4))
/* Alias word address of BDRST bit */
#define BDRST_BitNumber 0x10
#define BDCR_BDRST_BB (PERIPH_BB_BASE + (BDCR_OFFSET * 32) + (BDRST_BitNumber * 4))
/* --- CSR Register ---*/
/* Alias word address of LSION bit */
#define CSR_OFFSET (RCC_OFFSET + 0x24)
#define LSION_BitNumber 0x00
#define CSR_LSION_BB (PERIPH_BB_BASE + (CSR_OFFSET * 32) + (LSION_BitNumber * 4))
#ifdef STM32F10X_CL
/* --- CFGR2 Register ---*/
/* Alias word address of I2S2SRC bit */
#define CFGR2_OFFSET (RCC_OFFSET + 0x2C)
#define I2S2SRC_BitNumber 0x11
#define CFGR2_I2S2SRC_BB (PERIPH_BB_BASE + (CFGR2_OFFSET * 32) + (I2S2SRC_BitNumber * 4))
/* Alias word address of I2S3SRC bit */
#define I2S3SRC_BitNumber 0x12
#define CFGR2_I2S3SRC_BB (PERIPH_BB_BASE + (CFGR2_OFFSET * 32) + (I2S3SRC_BitNumber * 4))
#endif /* STM32F10X_CL */
/* ---------------------- RCC registers bit mask ------------------------ */
/* CR register bit mask */
#define CR_HSEBYP_Reset ((uint32_t)0xFFFBFFFF)
#define CR_HSEBYP_Set ((uint32_t)0x00040000)
#define CR_HSEON_Reset ((uint32_t)0xFFFEFFFF)
#define CR_HSEON_Set ((uint32_t)0x00010000)
#define CR_HSITRIM_Mask ((uint32_t)0xFFFFFF07)
/* CFGR register bit mask */
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL)
#define CFGR_PLL_Mask ((uint32_t)0xFFC2FFFF)
#else
#define CFGR_PLL_Mask ((uint32_t)0xFFC0FFFF)
#endif /* STM32F10X_CL */
#define CFGR_PLLMull_Mask ((uint32_t)0x003C0000)
#define CFGR_PLLSRC_Mask ((uint32_t)0x00010000)
#define CFGR_PLLXTPRE_Mask ((uint32_t)0x00020000)
#define CFGR_SWS_Mask ((uint32_t)0x0000000C)
#define CFGR_SW_Mask ((uint32_t)0xFFFFFFFC)
#define CFGR_HPRE_Reset_Mask ((uint32_t)0xFFFFFF0F)
#define CFGR_HPRE_Set_Mask ((uint32_t)0x000000F0)
#define CFGR_PPRE1_Reset_Mask ((uint32_t)0xFFFFF8FF)
#define CFGR_PPRE1_Set_Mask ((uint32_t)0x00000700)
#define CFGR_PPRE2_Reset_Mask ((uint32_t)0xFFFFC7FF)
#define CFGR_PPRE2_Set_Mask ((uint32_t)0x00003800)
#define CFGR_ADCPRE_Reset_Mask ((uint32_t)0xFFFF3FFF)
#define CFGR_ADCPRE_Set_Mask ((uint32_t)0x0000C000)
/* CSR register bit mask */
#define CSR_RMVF_Set ((uint32_t)0x01000000)
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL)
/* CFGR2 register bit mask */
#define CFGR2_PREDIV1SRC ((uint32_t)0x00010000)
#define CFGR2_PREDIV1 ((uint32_t)0x0000000F)
#endif
#ifdef STM32F10X_CL
#define CFGR2_PREDIV2 ((uint32_t)0x000000F0)
#define CFGR2_PLL2MUL ((uint32_t)0x00000F00)
#define CFGR2_PLL3MUL ((uint32_t)0x0000F000)
#endif /* STM32F10X_CL */
/* RCC Flag Mask */
#define FLAG_Mask ((uint8_t)0x1F)
/* CIR register byte 2 (Bits[15:8]) base address */
#define CIR_BYTE2_ADDRESS ((uint32_t)0x40021009)
/* CIR register byte 3 (Bits[23:16]) base address */
#define CIR_BYTE3_ADDRESS ((uint32_t)0x4002100A)
/* CFGR register byte 4 (Bits[31:24]) base address */
#define CFGR_BYTE4_ADDRESS ((uint32_t)0x40021007)
/* BDCR register base address */
#define BDCR_ADDRESS (PERIPH_BASE + BDCR_OFFSET)
/**
* @}
*/
/** @defgroup RCC_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup RCC_Private_Variables
* @{
*/
static __I uint8_t APBAHBPrescTable[16] = {0, 0, 0, 0, 1, 2, 3, 4, 1, 2, 3, 4, 6, 7, 8, 9};
static __I uint8_t ADCPrescTable[4] = {2, 4, 6, 8};
/**
* @}
*/
/** @defgroup RCC_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup RCC_Private_Functions
* @{
*/
/**
* @brief Resets the RCC clock configuration to the default reset state.
* @param None
* @retval None
*/
void RCC_DeInit(void)
{
/* Set HSION bit */
RCC->CR |= (uint32_t)0x00000001;
/* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */
#ifndef STM32F10X_CL
RCC->CFGR &= (uint32_t)0xF8FF0000;
#else
RCC->CFGR &= (uint32_t)0xF0FF0000;
#endif /* STM32F10X_CL */
/* Reset HSEON, CSSON and PLLON bits */
RCC->CR &= (uint32_t)0xFEF6FFFF;
/* Reset HSEBYP bit */
RCC->CR &= (uint32_t)0xFFFBFFFF;
/* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */
RCC->CFGR &= (uint32_t)0xFF80FFFF;
#ifdef STM32F10X_CL
/* Reset PLL2ON and PLL3ON bits */
RCC->CR &= (uint32_t)0xEBFFFFFF;
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x00FF0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
/* Reset CFGR2 register */
RCC->CFGR2 = 0x00000000;
#else
/* Disable all interrupts and clear pending bits */
RCC->CIR = 0x009F0000;
#endif /* STM32F10X_CL */
}
/**
* @brief Configures the External High Speed oscillator (HSE).
* @note HSE can not be stopped if it is used directly or through the PLL as system clock.
* @param RCC_HSE: specifies the new state of the HSE.
* This parameter can be one of the following values:
* @arg RCC_HSE_OFF: HSE oscillator OFF
* @arg RCC_HSE_ON: HSE oscillator ON
* @arg RCC_HSE_Bypass: HSE oscillator bypassed with external clock
* @retval None
*/
void RCC_HSEConfig(uint32_t RCC_HSE)
{
/* Check the parameters */
assert_param(IS_RCC_HSE(RCC_HSE));
/* Reset HSEON and HSEBYP bits before configuring the HSE ------------------*/
/* Reset HSEON bit */
RCC->CR &= CR_HSEON_Reset;
/* Reset HSEBYP bit */
RCC->CR &= CR_HSEBYP_Reset;
/* Configure HSE (RCC_HSE_OFF is already covered by the code section above) */
switch(RCC_HSE)
{
case RCC_HSE_ON:
/* Set HSEON bit */
RCC->CR |= CR_HSEON_Set;
break;
case RCC_HSE_Bypass:
/* Set HSEBYP and HSEON bits */
RCC->CR |= CR_HSEBYP_Set | CR_HSEON_Set;
break;
default:
break;
}
}
/**
* @brief Waits for HSE start-up.
* @param None
* @retval An ErrorStatus enumuration value:
* - SUCCESS: HSE oscillator is stable and ready to use
* - ERROR: HSE oscillator not yet ready
*/
ErrorStatus RCC_WaitForHSEStartUp(void)
{
__IO uint32_t StartUpCounter = 0;
ErrorStatus status = ERROR;
FlagStatus HSEStatus = RESET;
/* Wait till HSE is ready and if Time out is reached exit */
do
{
HSEStatus = RCC_GetFlagStatus(RCC_FLAG_HSERDY);
StartUpCounter++;
} while((StartUpCounter != HSE_STARTUP_TIMEOUT) && (HSEStatus == RESET));
if (RCC_GetFlagStatus(RCC_FLAG_HSERDY) != RESET)
{
status = SUCCESS;
}
else
{
status = ERROR;
}
return (status);
}
/**
* @brief Adjusts the Internal High Speed oscillator (HSI) calibration value.
* @param HSICalibrationValue: specifies the calibration trimming value.
* This parameter must be a number between 0 and 0x1F.
* @retval None
*/
void RCC_AdjustHSICalibrationValue(uint8_t HSICalibrationValue)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_CALIBRATION_VALUE(HSICalibrationValue));
tmpreg = RCC->CR;
/* Clear HSITRIM[4:0] bits */
tmpreg &= CR_HSITRIM_Mask;
/* Set the HSITRIM[4:0] bits according to HSICalibrationValue value */
tmpreg |= (uint32_t)HSICalibrationValue << 3;
/* Store the new value */
RCC->CR = tmpreg;
}
/**
* @brief Enables or disables the Internal High Speed oscillator (HSI).
* @note HSI can not be stopped if it is used directly or through the PLL as system clock.
* @param NewState: new state of the HSI. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_HSICmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CR_HSION_BB = (uint32_t)NewState;
}
/**
* @brief Configures the PLL clock source and multiplication factor.
* @note This function must be used only when the PLL is disabled.
* @param RCC_PLLSource: specifies the PLL entry clock source.
* For @b STM32_Connectivity_line_devices or @b STM32_Value_line_devices,
* this parameter can be one of the following values:
* @arg RCC_PLLSource_HSI_Div2: HSI oscillator clock divided by 2 selected as PLL clock entry
* @arg RCC_PLLSource_PREDIV1: PREDIV1 clock selected as PLL clock entry
* For @b other_STM32_devices, this parameter can be one of the following values:
* @arg RCC_PLLSource_HSI_Div2: HSI oscillator clock divided by 2 selected as PLL clock entry
* @arg RCC_PLLSource_HSE_Div1: HSE oscillator clock selected as PLL clock entry
* @arg RCC_PLLSource_HSE_Div2: HSE oscillator clock divided by 2 selected as PLL clock entry
* @param RCC_PLLMul: specifies the PLL multiplication factor.
* For @b STM32_Connectivity_line_devices, this parameter can be RCC_PLLMul_x where x:{[4,9], 6_5}
* For @b other_STM32_devices, this parameter can be RCC_PLLMul_x where x:[2,16]
* @retval None
*/
void RCC_PLLConfig(uint32_t RCC_PLLSource, uint32_t RCC_PLLMul)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_PLL_SOURCE(RCC_PLLSource));
assert_param(IS_RCC_PLL_MUL(RCC_PLLMul));
tmpreg = RCC->CFGR;
/* Clear PLLSRC, PLLXTPRE and PLLMUL[3:0] bits */
tmpreg &= CFGR_PLL_Mask;
/* Set the PLL configuration bits */
tmpreg |= RCC_PLLSource | RCC_PLLMul;
/* Store the new value */
RCC->CFGR = tmpreg;
}
/**
* @brief Enables or disables the PLL.
* @note The PLL can not be disabled if it is used as system clock.
* @param NewState: new state of the PLL. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_PLLCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CR_PLLON_BB = (uint32_t)NewState;
}
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL)
/**
* @brief Configures the PREDIV1 division factor.
* @note
* - This function must be used only when the PLL is disabled.
* - This function applies only to STM32 Connectivity line and Value line
* devices.
* @param RCC_PREDIV1_Source: specifies the PREDIV1 clock source.
* This parameter can be one of the following values:
* @arg RCC_PREDIV1_Source_HSE: HSE selected as PREDIV1 clock
* @arg RCC_PREDIV1_Source_PLL2: PLL2 selected as PREDIV1 clock
* @note
* For @b STM32_Value_line_devices this parameter is always RCC_PREDIV1_Source_HSE
* @param RCC_PREDIV1_Div: specifies the PREDIV1 clock division factor.
* This parameter can be RCC_PREDIV1_Divx where x:[1,16]
* @retval None
*/
void RCC_PREDIV1Config(uint32_t RCC_PREDIV1_Source, uint32_t RCC_PREDIV1_Div)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_PREDIV1_SOURCE(RCC_PREDIV1_Source));
assert_param(IS_RCC_PREDIV1(RCC_PREDIV1_Div));
tmpreg = RCC->CFGR2;
/* Clear PREDIV1[3:0] and PREDIV1SRC bits */
tmpreg &= ~(CFGR2_PREDIV1 | CFGR2_PREDIV1SRC);
/* Set the PREDIV1 clock source and division factor */
tmpreg |= RCC_PREDIV1_Source | RCC_PREDIV1_Div ;
/* Store the new value */
RCC->CFGR2 = tmpreg;
}
#endif
#ifdef STM32F10X_CL
/**
* @brief Configures the PREDIV2 division factor.
* @note
* - This function must be used only when both PLL2 and PLL3 are disabled.
* - This function applies only to STM32 Connectivity line devices.
* @param RCC_PREDIV2_Div: specifies the PREDIV2 clock division factor.
* This parameter can be RCC_PREDIV2_Divx where x:[1,16]
* @retval None
*/
void RCC_PREDIV2Config(uint32_t RCC_PREDIV2_Div)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_PREDIV2(RCC_PREDIV2_Div));
tmpreg = RCC->CFGR2;
/* Clear PREDIV2[3:0] bits */
tmpreg &= ~CFGR2_PREDIV2;
/* Set the PREDIV2 division factor */
tmpreg |= RCC_PREDIV2_Div;
/* Store the new value */
RCC->CFGR2 = tmpreg;
}
/**
* @brief Configures the PLL2 multiplication factor.
* @note
* - This function must be used only when the PLL2 is disabled.
* - This function applies only to STM32 Connectivity line devices.
* @param RCC_PLL2Mul: specifies the PLL2 multiplication factor.
* This parameter can be RCC_PLL2Mul_x where x:{[8,14], 16, 20}
* @retval None
*/
void RCC_PLL2Config(uint32_t RCC_PLL2Mul)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_PLL2_MUL(RCC_PLL2Mul));
tmpreg = RCC->CFGR2;
/* Clear PLL2Mul[3:0] bits */
tmpreg &= ~CFGR2_PLL2MUL;
/* Set the PLL2 configuration bits */
tmpreg |= RCC_PLL2Mul;
/* Store the new value */
RCC->CFGR2 = tmpreg;
}
/**
* @brief Enables or disables the PLL2.
* @note
* - The PLL2 can not be disabled if it is used indirectly as system clock
* (i.e. it is used as PLL clock entry that is used as System clock).
* - This function applies only to STM32 Connectivity line devices.
* @param NewState: new state of the PLL2. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_PLL2Cmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CR_PLL2ON_BB = (uint32_t)NewState;
}
/**
* @brief Configures the PLL3 multiplication factor.
* @note
* - This function must be used only when the PLL3 is disabled.
* - This function applies only to STM32 Connectivity line devices.
* @param RCC_PLL3Mul: specifies the PLL3 multiplication factor.
* This parameter can be RCC_PLL3Mul_x where x:{[8,14], 16, 20}
* @retval None
*/
void RCC_PLL3Config(uint32_t RCC_PLL3Mul)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_PLL3_MUL(RCC_PLL3Mul));
tmpreg = RCC->CFGR2;
/* Clear PLL3Mul[3:0] bits */
tmpreg &= ~CFGR2_PLL3MUL;
/* Set the PLL3 configuration bits */
tmpreg |= RCC_PLL3Mul;
/* Store the new value */
RCC->CFGR2 = tmpreg;
}
/**
* @brief Enables or disables the PLL3.
* @note This function applies only to STM32 Connectivity line devices.
* @param NewState: new state of the PLL3. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_PLL3Cmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CR_PLL3ON_BB = (uint32_t)NewState;
}
#endif /* STM32F10X_CL */
/**
* @brief Configures the system clock (SYSCLK).
* @param RCC_SYSCLKSource: specifies the clock source used as system clock.
* This parameter can be one of the following values:
* @arg RCC_SYSCLKSource_HSI: HSI selected as system clock
* @arg RCC_SYSCLKSource_HSE: HSE selected as system clock
* @arg RCC_SYSCLKSource_PLLCLK: PLL selected as system clock
* @retval None
*/
void RCC_SYSCLKConfig(uint32_t RCC_SYSCLKSource)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_SYSCLK_SOURCE(RCC_SYSCLKSource));
tmpreg = RCC->CFGR;
/* Clear SW[1:0] bits */
tmpreg &= CFGR_SW_Mask;
/* Set SW[1:0] bits according to RCC_SYSCLKSource value */
tmpreg |= RCC_SYSCLKSource;
/* Store the new value */
RCC->CFGR = tmpreg;
}
/**
* @brief Returns the clock source used as system clock.
* @param None
* @retval The clock source used as system clock. The returned value can
* be one of the following:
* - 0x00: HSI used as system clock
* - 0x04: HSE used as system clock
* - 0x08: PLL used as system clock
*/
uint8_t RCC_GetSYSCLKSource(void)
{
return ((uint8_t)(RCC->CFGR & CFGR_SWS_Mask));
}
/**
* @brief Configures the AHB clock (HCLK).
* @param RCC_SYSCLK: defines the AHB clock divider. This clock is derived from
* the system clock (SYSCLK).
* This parameter can be one of the following values:
* @arg RCC_SYSCLK_Div1: AHB clock = SYSCLK
* @arg RCC_SYSCLK_Div2: AHB clock = SYSCLK/2
* @arg RCC_SYSCLK_Div4: AHB clock = SYSCLK/4
* @arg RCC_SYSCLK_Div8: AHB clock = SYSCLK/8
* @arg RCC_SYSCLK_Div16: AHB clock = SYSCLK/16
* @arg RCC_SYSCLK_Div64: AHB clock = SYSCLK/64
* @arg RCC_SYSCLK_Div128: AHB clock = SYSCLK/128
* @arg RCC_SYSCLK_Div256: AHB clock = SYSCLK/256
* @arg RCC_SYSCLK_Div512: AHB clock = SYSCLK/512
* @retval None
*/
void RCC_HCLKConfig(uint32_t RCC_SYSCLK)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_HCLK(RCC_SYSCLK));
tmpreg = RCC->CFGR;
/* Clear HPRE[3:0] bits */
tmpreg &= CFGR_HPRE_Reset_Mask;
/* Set HPRE[3:0] bits according to RCC_SYSCLK value */
tmpreg |= RCC_SYSCLK;
/* Store the new value */
RCC->CFGR = tmpreg;
}
/**
* @brief Configures the Low Speed APB clock (PCLK1).
* @param RCC_HCLK: defines the APB1 clock divider. This clock is derived from
* the AHB clock (HCLK).
* This parameter can be one of the following values:
* @arg RCC_HCLK_Div1: APB1 clock = HCLK
* @arg RCC_HCLK_Div2: APB1 clock = HCLK/2
* @arg RCC_HCLK_Div4: APB1 clock = HCLK/4
* @arg RCC_HCLK_Div8: APB1 clock = HCLK/8
* @arg RCC_HCLK_Div16: APB1 clock = HCLK/16
* @retval None
*/
void RCC_PCLK1Config(uint32_t RCC_HCLK)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_PCLK(RCC_HCLK));
tmpreg = RCC->CFGR;
/* Clear PPRE1[2:0] bits */
tmpreg &= CFGR_PPRE1_Reset_Mask;
/* Set PPRE1[2:0] bits according to RCC_HCLK value */
tmpreg |= RCC_HCLK;
/* Store the new value */
RCC->CFGR = tmpreg;
}
/**
* @brief Configures the High Speed APB clock (PCLK2).
* @param RCC_HCLK: defines the APB2 clock divider. This clock is derived from
* the AHB clock (HCLK).
* This parameter can be one of the following values:
* @arg RCC_HCLK_Div1: APB2 clock = HCLK
* @arg RCC_HCLK_Div2: APB2 clock = HCLK/2
* @arg RCC_HCLK_Div4: APB2 clock = HCLK/4
* @arg RCC_HCLK_Div8: APB2 clock = HCLK/8
* @arg RCC_HCLK_Div16: APB2 clock = HCLK/16
* @retval None
*/
void RCC_PCLK2Config(uint32_t RCC_HCLK)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_PCLK(RCC_HCLK));
tmpreg = RCC->CFGR;
/* Clear PPRE2[2:0] bits */
tmpreg &= CFGR_PPRE2_Reset_Mask;
/* Set PPRE2[2:0] bits according to RCC_HCLK value */
tmpreg |= RCC_HCLK << 3;
/* Store the new value */
RCC->CFGR = tmpreg;
}
/**
* @brief Enables or disables the specified RCC interrupts.
* @param RCC_IT: specifies the RCC interrupt sources to be enabled or disabled.
*
* For @b STM32_Connectivity_line_devices, this parameter can be any combination
* of the following values
* @arg RCC_IT_LSIRDY: LSI ready interrupt
* @arg RCC_IT_LSERDY: LSE ready interrupt
* @arg RCC_IT_HSIRDY: HSI ready interrupt
* @arg RCC_IT_HSERDY: HSE ready interrupt
* @arg RCC_IT_PLLRDY: PLL ready interrupt
* @arg RCC_IT_PLL2RDY: PLL2 ready interrupt
* @arg RCC_IT_PLL3RDY: PLL3 ready interrupt
*
* For @b other_STM32_devices, this parameter can be any combination of the
* following values
* @arg RCC_IT_LSIRDY: LSI ready interrupt
* @arg RCC_IT_LSERDY: LSE ready interrupt
* @arg RCC_IT_HSIRDY: HSI ready interrupt
* @arg RCC_IT_HSERDY: HSE ready interrupt
* @arg RCC_IT_PLLRDY: PLL ready interrupt
*
* @param NewState: new state of the specified RCC interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_ITConfig(uint8_t RCC_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_IT(RCC_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Perform Byte access to RCC_CIR bits to enable the selected interrupts */
*(__IO uint8_t *) CIR_BYTE2_ADDRESS |= RCC_IT;
}
else
{
/* Perform Byte access to RCC_CIR bits to disable the selected interrupts */
*(__IO uint8_t *) CIR_BYTE2_ADDRESS &= (uint8_t)~RCC_IT;
}
}
#ifndef STM32F10X_CL
/**
* @brief Configures the USB clock (USBCLK).
* @param RCC_USBCLKSource: specifies the USB clock source. This clock is
* derived from the PLL output.
* This parameter can be one of the following values:
* @arg RCC_USBCLKSource_PLLCLK_1Div5: PLL clock divided by 1,5 selected as USB
* clock source
* @arg RCC_USBCLKSource_PLLCLK_Div1: PLL clock selected as USB clock source
* @retval None
*/
void RCC_USBCLKConfig(uint32_t RCC_USBCLKSource)
{
/* Check the parameters */
assert_param(IS_RCC_USBCLK_SOURCE(RCC_USBCLKSource));
*(__IO uint32_t *) CFGR_USBPRE_BB = RCC_USBCLKSource;
}
#else
/**
* @brief Configures the USB OTG FS clock (OTGFSCLK).
* This function applies only to STM32 Connectivity line devices.
* @param RCC_OTGFSCLKSource: specifies the USB OTG FS clock source.
* This clock is derived from the PLL output.
* This parameter can be one of the following values:
* @arg RCC_OTGFSCLKSource_PLLVCO_Div3: PLL VCO clock divided by 2 selected as USB OTG FS clock source
* @arg RCC_OTGFSCLKSource_PLLVCO_Div2: PLL VCO clock divided by 2 selected as USB OTG FS clock source
* @retval None
*/
void RCC_OTGFSCLKConfig(uint32_t RCC_OTGFSCLKSource)
{
/* Check the parameters */
assert_param(IS_RCC_OTGFSCLK_SOURCE(RCC_OTGFSCLKSource));
*(__IO uint32_t *) CFGR_OTGFSPRE_BB = RCC_OTGFSCLKSource;
}
#endif /* STM32F10X_CL */
/**
* @brief Configures the ADC clock (ADCCLK).
* @param RCC_PCLK2: defines the ADC clock divider. This clock is derived from
* the APB2 clock (PCLK2).
* This parameter can be one of the following values:
* @arg RCC_PCLK2_Div2: ADC clock = PCLK2/2
* @arg RCC_PCLK2_Div4: ADC clock = PCLK2/4
* @arg RCC_PCLK2_Div6: ADC clock = PCLK2/6
* @arg RCC_PCLK2_Div8: ADC clock = PCLK2/8
* @retval None
*/
void RCC_ADCCLKConfig(uint32_t RCC_PCLK2)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RCC_ADCCLK(RCC_PCLK2));
tmpreg = RCC->CFGR;
/* Clear ADCPRE[1:0] bits */
tmpreg &= CFGR_ADCPRE_Reset_Mask;
/* Set ADCPRE[1:0] bits according to RCC_PCLK2 value */
tmpreg |= RCC_PCLK2;
/* Store the new value */
RCC->CFGR = tmpreg;
}
#ifdef STM32F10X_CL
/**
* @brief Configures the I2S2 clock source(I2S2CLK).
* @note
* - This function must be called before enabling I2S2 APB clock.
* - This function applies only to STM32 Connectivity line devices.
* @param RCC_I2S2CLKSource: specifies the I2S2 clock source.
* This parameter can be one of the following values:
* @arg RCC_I2S2CLKSource_SYSCLK: system clock selected as I2S2 clock entry
* @arg RCC_I2S2CLKSource_PLL3_VCO: PLL3 VCO clock selected as I2S2 clock entry
* @retval None
*/
void RCC_I2S2CLKConfig(uint32_t RCC_I2S2CLKSource)
{
/* Check the parameters */
assert_param(IS_RCC_I2S2CLK_SOURCE(RCC_I2S2CLKSource));
*(__IO uint32_t *) CFGR2_I2S2SRC_BB = RCC_I2S2CLKSource;
}
/**
* @brief Configures the I2S3 clock source(I2S2CLK).
* @note
* - This function must be called before enabling I2S3 APB clock.
* - This function applies only to STM32 Connectivity line devices.
* @param RCC_I2S3CLKSource: specifies the I2S3 clock source.
* This parameter can be one of the following values:
* @arg RCC_I2S3CLKSource_SYSCLK: system clock selected as I2S3 clock entry
* @arg RCC_I2S3CLKSource_PLL3_VCO: PLL3 VCO clock selected as I2S3 clock entry
* @retval None
*/
void RCC_I2S3CLKConfig(uint32_t RCC_I2S3CLKSource)
{
/* Check the parameters */
assert_param(IS_RCC_I2S3CLK_SOURCE(RCC_I2S3CLKSource));
*(__IO uint32_t *) CFGR2_I2S3SRC_BB = RCC_I2S3CLKSource;
}
#endif /* STM32F10X_CL */
/**
* @brief Configures the External Low Speed oscillator (LSE).
* @param RCC_LSE: specifies the new state of the LSE.
* This parameter can be one of the following values:
* @arg RCC_LSE_OFF: LSE oscillator OFF
* @arg RCC_LSE_ON: LSE oscillator ON
* @arg RCC_LSE_Bypass: LSE oscillator bypassed with external clock
* @retval None
*/
void RCC_LSEConfig(uint8_t RCC_LSE)
{
/* Check the parameters */
assert_param(IS_RCC_LSE(RCC_LSE));
/* Reset LSEON and LSEBYP bits before configuring the LSE ------------------*/
/* Reset LSEON bit */
*(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_OFF;
/* Reset LSEBYP bit */
*(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_OFF;
/* Configure LSE (RCC_LSE_OFF is already covered by the code section above) */
switch(RCC_LSE)
{
case RCC_LSE_ON:
/* Set LSEON bit */
*(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_ON;
break;
case RCC_LSE_Bypass:
/* Set LSEBYP and LSEON bits */
*(__IO uint8_t *) BDCR_ADDRESS = RCC_LSE_Bypass | RCC_LSE_ON;
break;
default:
break;
}
}
/**
* @brief Enables or disables the Internal Low Speed oscillator (LSI).
* @note LSI can not be disabled if the IWDG is running.
* @param NewState: new state of the LSI. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_LSICmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CSR_LSION_BB = (uint32_t)NewState;
}
/**
* @brief Configures the RTC clock (RTCCLK).
* @note Once the RTC clock is selected it can't be changed unless the Backup domain is reset.
* @param RCC_RTCCLKSource: specifies the RTC clock source.
* This parameter can be one of the following values:
* @arg RCC_RTCCLKSource_LSE: LSE selected as RTC clock
* @arg RCC_RTCCLKSource_LSI: LSI selected as RTC clock
* @arg RCC_RTCCLKSource_HSE_Div128: HSE clock divided by 128 selected as RTC clock
* @retval None
*/
void RCC_RTCCLKConfig(uint32_t RCC_RTCCLKSource)
{
/* Check the parameters */
assert_param(IS_RCC_RTCCLK_SOURCE(RCC_RTCCLKSource));
/* Select the RTC clock source */
RCC->BDCR |= RCC_RTCCLKSource;
}
/**
* @brief Enables or disables the RTC clock.
* @note This function must be used only after the RTC clock was selected using the RCC_RTCCLKConfig function.
* @param NewState: new state of the RTC clock. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_RTCCLKCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) BDCR_RTCEN_BB = (uint32_t)NewState;
}
/**
* @brief Returns the frequencies of different on chip clocks.
* @param RCC_Clocks: pointer to a RCC_ClocksTypeDef structure which will hold
* the clocks frequencies.
* @note The result of this function could be not correct when using
* fractional value for HSE crystal.
* @retval None
*/
void RCC_GetClocksFreq(RCC_ClocksTypeDef* RCC_Clocks)
{
uint32_t tmp = 0, pllmull = 0, pllsource = 0, presc = 0;
#ifdef STM32F10X_CL
uint32_t prediv1source = 0, prediv1factor = 0, prediv2factor = 0, pll2mull = 0;
#endif /* STM32F10X_CL */
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
uint32_t prediv1factor = 0;
#endif
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & CFGR_SWS_Mask;
switch (tmp)
{
case 0x00: /* HSI used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
break;
case 0x04: /* HSE used as system clock */
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE;
break;
case 0x08: /* PLL used as system clock */
/* Get PLL clock source and multiplication factor ----------------------*/
pllmull = RCC->CFGR & CFGR_PLLMull_Mask;
pllsource = RCC->CFGR & CFGR_PLLSRC_Mask;
#ifndef STM32F10X_CL
pllmull = ( pllmull >> 18) + 2;
if (pllsource == 0x00)
{/* HSI oscillator clock divided by 2 selected as PLL clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
}
else
{
#if defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || defined (STM32F10X_HD_VL)
prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
/* HSE oscillator clock selected as PREDIV1 clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull;
#else
/* HSE selected as PLL clock entry */
if ((RCC->CFGR & CFGR_PLLXTPRE_Mask) != (uint32_t)RESET)
{/* HSE oscillator clock divided by 2 */
RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE >> 1) * pllmull;
}
else
{
RCC_Clocks->SYSCLK_Frequency = HSE_VALUE * pllmull;
}
#endif
}
#else
pllmull = pllmull >> 18;
if (pllmull != 0x0D)
{
pllmull += 2;
}
else
{ /* PLL multiplication factor = PLL input clock * 6.5 */
pllmull = 13 / 2;
}
if (pllsource == 0x00)
{/* HSI oscillator clock divided by 2 selected as PLL clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSI_VALUE >> 1) * pllmull;
}
else
{/* PREDIV1 selected as PLL clock entry */
/* Get PREDIV1 clock source and division factor */
prediv1source = RCC->CFGR2 & CFGR2_PREDIV1SRC;
prediv1factor = (RCC->CFGR2 & CFGR2_PREDIV1) + 1;
if (prediv1source == 0)
{ /* HSE oscillator clock selected as PREDIV1 clock entry */
RCC_Clocks->SYSCLK_Frequency = (HSE_VALUE / prediv1factor) * pllmull;
}
else
{/* PLL2 clock selected as PREDIV1 clock entry */
/* Get PREDIV2 division factor and PLL2 multiplication factor */
prediv2factor = ((RCC->CFGR2 & CFGR2_PREDIV2) >> 4) + 1;
pll2mull = ((RCC->CFGR2 & CFGR2_PLL2MUL) >> 8 ) + 2;
RCC_Clocks->SYSCLK_Frequency = (((HSE_VALUE / prediv2factor) * pll2mull) / prediv1factor) * pllmull;
}
}
#endif /* STM32F10X_CL */
break;
default:
RCC_Clocks->SYSCLK_Frequency = HSI_VALUE;
break;
}
/* Compute HCLK, PCLK1, PCLK2 and ADCCLK clocks frequencies ----------------*/
/* Get HCLK prescaler */
tmp = RCC->CFGR & CFGR_HPRE_Set_Mask;
tmp = tmp >> 4;
presc = APBAHBPrescTable[tmp];
/* HCLK clock frequency */
RCC_Clocks->HCLK_Frequency = RCC_Clocks->SYSCLK_Frequency >> presc;
/* Get PCLK1 prescaler */
tmp = RCC->CFGR & CFGR_PPRE1_Set_Mask;
tmp = tmp >> 8;
presc = APBAHBPrescTable[tmp];
/* PCLK1 clock frequency */
RCC_Clocks->PCLK1_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
/* Get PCLK2 prescaler */
tmp = RCC->CFGR & CFGR_PPRE2_Set_Mask;
tmp = tmp >> 11;
presc = APBAHBPrescTable[tmp];
/* PCLK2 clock frequency */
RCC_Clocks->PCLK2_Frequency = RCC_Clocks->HCLK_Frequency >> presc;
/* Get ADCCLK prescaler */
tmp = RCC->CFGR & CFGR_ADCPRE_Set_Mask;
tmp = tmp >> 14;
presc = ADCPrescTable[tmp];
/* ADCCLK clock frequency */
RCC_Clocks->ADCCLK_Frequency = RCC_Clocks->PCLK2_Frequency / presc;
}
/**
* @brief Enables or disables the AHB peripheral clock.
* @param RCC_AHBPeriph: specifies the AHB peripheral to gates its clock.
*
* For @b STM32_Connectivity_line_devices, this parameter can be any combination
* of the following values:
* @arg RCC_AHBPeriph_DMA1
* @arg RCC_AHBPeriph_DMA2
* @arg RCC_AHBPeriph_SRAM
* @arg RCC_AHBPeriph_FLITF
* @arg RCC_AHBPeriph_CRC
* @arg RCC_AHBPeriph_OTG_FS
* @arg RCC_AHBPeriph_ETH_MAC
* @arg RCC_AHBPeriph_ETH_MAC_Tx
* @arg RCC_AHBPeriph_ETH_MAC_Rx
*
* For @b other_STM32_devices, this parameter can be any combination of the
* following values:
* @arg RCC_AHBPeriph_DMA1
* @arg RCC_AHBPeriph_DMA2
* @arg RCC_AHBPeriph_SRAM
* @arg RCC_AHBPeriph_FLITF
* @arg RCC_AHBPeriph_CRC
* @arg RCC_AHBPeriph_FSMC
* @arg RCC_AHBPeriph_SDIO
*
* @note SRAM and FLITF clock can be disabled only during sleep mode.
* @param NewState: new state of the specified peripheral clock.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_AHB_PERIPH(RCC_AHBPeriph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->AHBENR |= RCC_AHBPeriph;
}
else
{
RCC->AHBENR &= ~RCC_AHBPeriph;
}
}
/**
* @brief Enables or disables the High Speed APB (APB2) peripheral clock.
* @param RCC_APB2Periph: specifies the APB2 peripheral to gates its clock.
* This parameter can be any combination of the following values:
* @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
* RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
* RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
* RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
* RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
* RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,
* RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11
* @param NewState: new state of the specified peripheral clock.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_APB2PeriphClockCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB2ENR |= RCC_APB2Periph;
}
else
{
RCC->APB2ENR &= ~RCC_APB2Periph;
}
}
/**
* @brief Enables or disables the Low Speed APB (APB1) peripheral clock.
* @param RCC_APB1Periph: specifies the APB1 peripheral to gates its clock.
* This parameter can be any combination of the following values:
* @arg RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4,
* RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7,
* RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3,
* RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4,
* RCC_APB1Periph_USART5, RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2,
* RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP,
* RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC,
* RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14
* @param NewState: new state of the specified peripheral clock.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB1ENR |= RCC_APB1Periph;
}
else
{
RCC->APB1ENR &= ~RCC_APB1Periph;
}
}
#ifdef STM32F10X_CL
/**
* @brief Forces or releases AHB peripheral reset.
* @note This function applies only to STM32 Connectivity line devices.
* @param RCC_AHBPeriph: specifies the AHB peripheral to reset.
* This parameter can be any combination of the following values:
* @arg RCC_AHBPeriph_OTG_FS
* @arg RCC_AHBPeriph_ETH_MAC
* @param NewState: new state of the specified peripheral reset.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_AHBPeriphResetCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_AHB_PERIPH_RESET(RCC_AHBPeriph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->AHBRSTR |= RCC_AHBPeriph;
}
else
{
RCC->AHBRSTR &= ~RCC_AHBPeriph;
}
}
#endif /* STM32F10X_CL */
/**
* @brief Forces or releases High Speed APB (APB2) peripheral reset.
* @param RCC_APB2Periph: specifies the APB2 peripheral to reset.
* This parameter can be any combination of the following values:
* @arg RCC_APB2Periph_AFIO, RCC_APB2Periph_GPIOA, RCC_APB2Periph_GPIOB,
* RCC_APB2Periph_GPIOC, RCC_APB2Periph_GPIOD, RCC_APB2Periph_GPIOE,
* RCC_APB2Periph_GPIOF, RCC_APB2Periph_GPIOG, RCC_APB2Periph_ADC1,
* RCC_APB2Periph_ADC2, RCC_APB2Periph_TIM1, RCC_APB2Periph_SPI1,
* RCC_APB2Periph_TIM8, RCC_APB2Periph_USART1, RCC_APB2Periph_ADC3,
* RCC_APB2Periph_TIM15, RCC_APB2Periph_TIM16, RCC_APB2Periph_TIM17,
* RCC_APB2Periph_TIM9, RCC_APB2Periph_TIM10, RCC_APB2Periph_TIM11
* @param NewState: new state of the specified peripheral reset.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_APB2PeriphResetCmd(uint32_t RCC_APB2Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_APB2_PERIPH(RCC_APB2Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB2RSTR |= RCC_APB2Periph;
}
else
{
RCC->APB2RSTR &= ~RCC_APB2Periph;
}
}
/**
* @brief Forces or releases Low Speed APB (APB1) peripheral reset.
* @param RCC_APB1Periph: specifies the APB1 peripheral to reset.
* This parameter can be any combination of the following values:
* @arg RCC_APB1Periph_TIM2, RCC_APB1Periph_TIM3, RCC_APB1Periph_TIM4,
* RCC_APB1Periph_TIM5, RCC_APB1Periph_TIM6, RCC_APB1Periph_TIM7,
* RCC_APB1Periph_WWDG, RCC_APB1Periph_SPI2, RCC_APB1Periph_SPI3,
* RCC_APB1Periph_USART2, RCC_APB1Periph_USART3, RCC_APB1Periph_USART4,
* RCC_APB1Periph_USART5, RCC_APB1Periph_I2C1, RCC_APB1Periph_I2C2,
* RCC_APB1Periph_USB, RCC_APB1Periph_CAN1, RCC_APB1Periph_BKP,
* RCC_APB1Periph_PWR, RCC_APB1Periph_DAC, RCC_APB1Periph_CEC,
* RCC_APB1Periph_TIM12, RCC_APB1Periph_TIM13, RCC_APB1Periph_TIM14
* @param NewState: new state of the specified peripheral clock.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_APB1PeriphResetCmd(uint32_t RCC_APB1Periph, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RCC_APB1_PERIPH(RCC_APB1Periph));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RCC->APB1RSTR |= RCC_APB1Periph;
}
else
{
RCC->APB1RSTR &= ~RCC_APB1Periph;
}
}
/**
* @brief Forces or releases the Backup domain reset.
* @param NewState: new state of the Backup domain reset.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_BackupResetCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) BDCR_BDRST_BB = (uint32_t)NewState;
}
/**
* @brief Enables or disables the Clock Security System.
* @param NewState: new state of the Clock Security System..
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RCC_ClockSecuritySystemCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CR_CSSON_BB = (uint32_t)NewState;
}
/**
* @brief Selects the clock source to output on MCO pin.
* @param RCC_MCO: specifies the clock source to output.
*
* For @b STM32_Connectivity_line_devices, this parameter can be one of the
* following values:
* @arg RCC_MCO_NoClock: No clock selected
* @arg RCC_MCO_SYSCLK: System clock selected
* @arg RCC_MCO_HSI: HSI oscillator clock selected
* @arg RCC_MCO_HSE: HSE oscillator clock selected
* @arg RCC_MCO_PLLCLK_Div2: PLL clock divided by 2 selected
* @arg RCC_MCO_PLL2CLK: PLL2 clock selected
* @arg RCC_MCO_PLL3CLK_Div2: PLL3 clock divided by 2 selected
* @arg RCC_MCO_XT1: External 3-25 MHz oscillator clock selected
* @arg RCC_MCO_PLL3CLK: PLL3 clock selected
*
* For @b other_STM32_devices, this parameter can be one of the following values:
* @arg RCC_MCO_NoClock: No clock selected
* @arg RCC_MCO_SYSCLK: System clock selected
* @arg RCC_MCO_HSI: HSI oscillator clock selected
* @arg RCC_MCO_HSE: HSE oscillator clock selected
* @arg RCC_MCO_PLLCLK_Div2: PLL clock divided by 2 selected
*
* @retval None
*/
void RCC_MCOConfig(uint8_t RCC_MCO)
{
/* Check the parameters */
assert_param(IS_RCC_MCO(RCC_MCO));
/* Perform Byte access to MCO bits to select the MCO source */
*(__IO uint8_t *) CFGR_BYTE4_ADDRESS = RCC_MCO;
}
/**
* @brief Checks whether the specified RCC flag is set or not.
* @param RCC_FLAG: specifies the flag to check.
*
* For @b STM32_Connectivity_line_devices, this parameter can be one of the
* following values:
* @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready
* @arg RCC_FLAG_HSERDY: HSE oscillator clock ready
* @arg RCC_FLAG_PLLRDY: PLL clock ready
* @arg RCC_FLAG_PLL2RDY: PLL2 clock ready
* @arg RCC_FLAG_PLL3RDY: PLL3 clock ready
* @arg RCC_FLAG_LSERDY: LSE oscillator clock ready
* @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready
* @arg RCC_FLAG_PINRST: Pin reset
* @arg RCC_FLAG_PORRST: POR/PDR reset
* @arg RCC_FLAG_SFTRST: Software reset
* @arg RCC_FLAG_IWDGRST: Independent Watchdog reset
* @arg RCC_FLAG_WWDGRST: Window Watchdog reset
* @arg RCC_FLAG_LPWRRST: Low Power reset
*
* For @b other_STM32_devices, this parameter can be one of the following values:
* @arg RCC_FLAG_HSIRDY: HSI oscillator clock ready
* @arg RCC_FLAG_HSERDY: HSE oscillator clock ready
* @arg RCC_FLAG_PLLRDY: PLL clock ready
* @arg RCC_FLAG_LSERDY: LSE oscillator clock ready
* @arg RCC_FLAG_LSIRDY: LSI oscillator clock ready
* @arg RCC_FLAG_PINRST: Pin reset
* @arg RCC_FLAG_PORRST: POR/PDR reset
* @arg RCC_FLAG_SFTRST: Software reset
* @arg RCC_FLAG_IWDGRST: Independent Watchdog reset
* @arg RCC_FLAG_WWDGRST: Window Watchdog reset
* @arg RCC_FLAG_LPWRRST: Low Power reset
*
* @retval The new state of RCC_FLAG (SET or RESET).
*/
FlagStatus RCC_GetFlagStatus(uint8_t RCC_FLAG)
{
uint32_t tmp = 0;
uint32_t statusreg = 0;
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_RCC_FLAG(RCC_FLAG));
/* Get the RCC register index */
tmp = RCC_FLAG >> 5;
if (tmp == 1) /* The flag to check is in CR register */
{
statusreg = RCC->CR;
}
else if (tmp == 2) /* The flag to check is in BDCR register */
{
statusreg = RCC->BDCR;
}
else /* The flag to check is in CSR register */
{
statusreg = RCC->CSR;
}
/* Get the flag position */
tmp = RCC_FLAG & FLAG_Mask;
if ((statusreg & ((uint32_t)1 << tmp)) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
/* Return the flag status */
return bitstatus;
}
/**
* @brief Clears the RCC reset flags.
* @note The reset flags are: RCC_FLAG_PINRST, RCC_FLAG_PORRST, RCC_FLAG_SFTRST,
* RCC_FLAG_IWDGRST, RCC_FLAG_WWDGRST, RCC_FLAG_LPWRRST
* @param None
* @retval None
*/
void RCC_ClearFlag(void)
{
/* Set RMVF bit to clear the reset flags */
RCC->CSR |= CSR_RMVF_Set;
}
/**
* @brief Checks whether the specified RCC interrupt has occurred or not.
* @param RCC_IT: specifies the RCC interrupt source to check.
*
* For @b STM32_Connectivity_line_devices, this parameter can be one of the
* following values:
* @arg RCC_IT_LSIRDY: LSI ready interrupt
* @arg RCC_IT_LSERDY: LSE ready interrupt
* @arg RCC_IT_HSIRDY: HSI ready interrupt
* @arg RCC_IT_HSERDY: HSE ready interrupt
* @arg RCC_IT_PLLRDY: PLL ready interrupt
* @arg RCC_IT_PLL2RDY: PLL2 ready interrupt
* @arg RCC_IT_PLL3RDY: PLL3 ready interrupt
* @arg RCC_IT_CSS: Clock Security System interrupt
*
* For @b other_STM32_devices, this parameter can be one of the following values:
* @arg RCC_IT_LSIRDY: LSI ready interrupt
* @arg RCC_IT_LSERDY: LSE ready interrupt
* @arg RCC_IT_HSIRDY: HSI ready interrupt
* @arg RCC_IT_HSERDY: HSE ready interrupt
* @arg RCC_IT_PLLRDY: PLL ready interrupt
* @arg RCC_IT_CSS: Clock Security System interrupt
*
* @retval The new state of RCC_IT (SET or RESET).
*/
ITStatus RCC_GetITStatus(uint8_t RCC_IT)
{
ITStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_RCC_GET_IT(RCC_IT));
/* Check the status of the specified RCC interrupt */
if ((RCC->CIR & RCC_IT) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
/* Return the RCC_IT status */
return bitstatus;
}
/**
* @brief Clears the RCC's interrupt pending bits.
* @param RCC_IT: specifies the interrupt pending bit to clear.
*
* For @b STM32_Connectivity_line_devices, this parameter can be any combination
* of the following values:
* @arg RCC_IT_LSIRDY: LSI ready interrupt
* @arg RCC_IT_LSERDY: LSE ready interrupt
* @arg RCC_IT_HSIRDY: HSI ready interrupt
* @arg RCC_IT_HSERDY: HSE ready interrupt
* @arg RCC_IT_PLLRDY: PLL ready interrupt
* @arg RCC_IT_PLL2RDY: PLL2 ready interrupt
* @arg RCC_IT_PLL3RDY: PLL3 ready interrupt
* @arg RCC_IT_CSS: Clock Security System interrupt
*
* For @b other_STM32_devices, this parameter can be any combination of the
* following values:
* @arg RCC_IT_LSIRDY: LSI ready interrupt
* @arg RCC_IT_LSERDY: LSE ready interrupt
* @arg RCC_IT_HSIRDY: HSI ready interrupt
* @arg RCC_IT_HSERDY: HSE ready interrupt
* @arg RCC_IT_PLLRDY: PLL ready interrupt
*
* @arg RCC_IT_CSS: Clock Security System interrupt
* @retval None
*/
void RCC_ClearITPendingBit(uint8_t RCC_IT)
{
/* Check the parameters */
assert_param(IS_RCC_CLEAR_IT(RCC_IT));
/* Perform Byte access to RCC_CIR[23:16] bits to clear the selected interrupt
pending bits */
*(__IO uint8_t *) CIR_BYTE3_ADDRESS = RCC_IT;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_rtc.c
================================================
/**
******************************************************************************
* @file stm32f10x_rtc.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the RTC firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_rtc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup RTC
* @brief RTC driver modules
* @{
*/
/** @defgroup RTC_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup RTC_Private_Defines
* @{
*/
#define RTC_LSB_MASK ((uint32_t)0x0000FFFF) /*!< RTC LSB Mask */
#define PRLH_MSB_MASK ((uint32_t)0x000F0000) /*!< RTC Prescaler MSB Mask */
/**
* @}
*/
/** @defgroup RTC_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup RTC_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup RTC_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup RTC_Private_Functions
* @{
*/
/**
* @brief Enables or disables the specified RTC interrupts.
* @param RTC_IT: specifies the RTC interrupts sources to be enabled or disabled.
* This parameter can be any combination of the following values:
* @arg RTC_IT_OW: Overflow interrupt
* @arg RTC_IT_ALR: Alarm interrupt
* @arg RTC_IT_SEC: Second interrupt
* @param NewState: new state of the specified RTC interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_RTC_IT(RTC_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
RTC->CRH |= RTC_IT;
}
else
{
RTC->CRH &= (uint16_t)~RTC_IT;
}
}
/**
* @brief Enters the RTC configuration mode.
* @param None
* @retval None
*/
void RTC_EnterConfigMode(void)
{
/* Set the CNF flag to enter in the Configuration Mode */
RTC->CRL |= RTC_CRL_CNF;
}
/**
* @brief Exits from the RTC configuration mode.
* @param None
* @retval None
*/
void RTC_ExitConfigMode(void)
{
/* Reset the CNF flag to exit from the Configuration Mode */
RTC->CRL &= (uint16_t)~((uint16_t)RTC_CRL_CNF);
}
/**
* @brief Gets the RTC counter value.
* @param None
* @retval RTC counter value.
*/
uint32_t RTC_GetCounter(void)
{
uint16_t tmp = 0;
tmp = RTC->CNTL;
return (((uint32_t)RTC->CNTH << 16 ) | tmp) ;
}
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/**
* @brief Sets the RTC counter value.
* @param CounterValue: RTC counter new value.
* @retval None
*/
void RTC_SetCounter(uint32_t CounterValue)
{
RTC_EnterConfigMode();
/* Set RTC COUNTER MSB word */
RTC->CNTH = CounterValue >> 16;
/* Set RTC COUNTER LSB word */
RTC->CNTL = (CounterValue & RTC_LSB_MASK);
RTC_ExitConfigMode();
}
/**
* @brief Sets the RTC prescaler value.
* @param PrescalerValue: RTC prescaler new value.
* @retval None
*/
void RTC_SetPrescaler(uint32_t PrescalerValue)
{
/* Check the parameters */
assert_param(IS_RTC_PRESCALER(PrescalerValue));
RTC_EnterConfigMode();
/* Set RTC PRESCALER MSB word */
RTC->PRLH = (PrescalerValue & PRLH_MSB_MASK) >> 16;
/* Set RTC PRESCALER LSB word */
RTC->PRLL = (PrescalerValue & RTC_LSB_MASK);
RTC_ExitConfigMode();
}
/**
* @brief Sets the RTC alarm value.
* @param AlarmValue: RTC alarm new value.
* @retval None
*/
void RTC_SetAlarm(uint32_t AlarmValue)
{
RTC_EnterConfigMode();
/* Set the ALARM MSB word */
RTC->ALRH = AlarmValue >> 16;
/* Set the ALARM LSB word */
RTC->ALRL = (AlarmValue & RTC_LSB_MASK);
RTC_ExitConfigMode();
}
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/**
* @brief Gets the RTC divider value.
* @param None
* @retval RTC Divider value.
*/
uint32_t RTC_GetDivider(void)
{
uint32_t tmp = 0x00;
tmp = ((uint32_t)RTC->DIVH & (uint32_t)0x000F) << 16;
tmp |= RTC->DIVL;
return tmp;
}
/**
* @brief Waits until last write operation on RTC registers has finished.
* @note This function must be called before any write to RTC registers.
* @param None
* @retval None
*/
void RTC_WaitForLastTask(void)
{
/* Loop until RTOFF flag is set */
while ((RTC->CRL & RTC_FLAG_RTOFF) == (uint16_t)RESET)
{
}
}
/**
* @brief Waits until the RTC registers (RTC_CNT, RTC_ALR and RTC_PRL)
* are synchronized with RTC APB clock.
* @note This function must be called before any read operation after an APB reset
* or an APB clock stop.
* @param None
* @retval None
*/
void RTC_WaitForSynchro(void)
{
/* Clear RSF flag */
RTC->CRL &= (uint16_t)~RTC_FLAG_RSF;
/* Loop until RSF flag is set */
while ((RTC->CRL & RTC_FLAG_RSF) == (uint16_t)RESET)
{
}
}
/**
* @brief Checks whether the specified RTC flag is set or not.
* @param RTC_FLAG: specifies the flag to check.
* This parameter can be one the following values:
* @arg RTC_FLAG_RTOFF: RTC Operation OFF flag
* @arg RTC_FLAG_RSF: Registers Synchronized flag
* @arg RTC_FLAG_OW: Overflow flag
* @arg RTC_FLAG_ALR: Alarm flag
* @arg RTC_FLAG_SEC: Second flag
* @retval The new state of RTC_FLAG (SET or RESET).
*/
FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_RTC_GET_FLAG(RTC_FLAG));
if ((RTC->CRL & RTC_FLAG) != (uint16_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the RTC's pending flags.
* @param RTC_FLAG: specifies the flag to clear.
* This parameter can be any combination of the following values:
* @arg RTC_FLAG_RSF: Registers Synchronized flag. This flag is cleared only after
* an APB reset or an APB Clock stop.
* @arg RTC_FLAG_OW: Overflow flag
* @arg RTC_FLAG_ALR: Alarm flag
* @arg RTC_FLAG_SEC: Second flag
* @retval None
*/
void RTC_ClearFlag(uint16_t RTC_FLAG)
{
/* Check the parameters */
assert_param(IS_RTC_CLEAR_FLAG(RTC_FLAG));
/* Clear the corresponding RTC flag */
RTC->CRL &= (uint16_t)~RTC_FLAG;
}
/**
* @brief Checks whether the specified RTC interrupt has occurred or not.
* @param RTC_IT: specifies the RTC interrupts sources to check.
* This parameter can be one of the following values:
* @arg RTC_IT_OW: Overflow interrupt
* @arg RTC_IT_ALR: Alarm interrupt
* @arg RTC_IT_SEC: Second interrupt
* @retval The new state of the RTC_IT (SET or RESET).
*/
ITStatus RTC_GetITStatus(uint16_t RTC_IT)
{
ITStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_RTC_GET_IT(RTC_IT));
bitstatus = (ITStatus)(RTC->CRL & RTC_IT);
if (((RTC->CRH & RTC_IT) != (uint16_t)RESET) && (bitstatus != (uint16_t)RESET))
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the RTC's interrupt pending bits.
* @param RTC_IT: specifies the interrupt pending bit to clear.
* This parameter can be any combination of the following values:
* @arg RTC_IT_OW: Overflow interrupt
* @arg RTC_IT_ALR: Alarm interrupt
* @arg RTC_IT_SEC: Second interrupt
* @retval None
*/
void RTC_ClearITPendingBit(uint16_t RTC_IT)
{
/* Check the parameters */
assert_param(IS_RTC_IT(RTC_IT));
/* Clear the corresponding RTC pending bit */
RTC->CRL &= (uint16_t)~RTC_IT;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_sdio.c
================================================
/**
******************************************************************************
* @file stm32f10x_sdio.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the SDIO firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_sdio.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup SDIO
* @brief SDIO driver modules
* @{
*/
/** @defgroup SDIO_Private_TypesDefinitions
* @{
*/
/* ------------ SDIO registers bit address in the alias region ----------- */
#define SDIO_OFFSET (SDIO_BASE - PERIPH_BASE)
/* --- CLKCR Register ---*/
/* Alias word address of CLKEN bit */
#define CLKCR_OFFSET (SDIO_OFFSET + 0x04)
#define CLKEN_BitNumber 0x08
#define CLKCR_CLKEN_BB (PERIPH_BB_BASE + (CLKCR_OFFSET * 32) + (CLKEN_BitNumber * 4))
/* --- CMD Register ---*/
/* Alias word address of SDIOSUSPEND bit */
#define CMD_OFFSET (SDIO_OFFSET + 0x0C)
#define SDIOSUSPEND_BitNumber 0x0B
#define CMD_SDIOSUSPEND_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (SDIOSUSPEND_BitNumber * 4))
/* Alias word address of ENCMDCOMPL bit */
#define ENCMDCOMPL_BitNumber 0x0C
#define CMD_ENCMDCOMPL_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ENCMDCOMPL_BitNumber * 4))
/* Alias word address of NIEN bit */
#define NIEN_BitNumber 0x0D
#define CMD_NIEN_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (NIEN_BitNumber * 4))
/* Alias word address of ATACMD bit */
#define ATACMD_BitNumber 0x0E
#define CMD_ATACMD_BB (PERIPH_BB_BASE + (CMD_OFFSET * 32) + (ATACMD_BitNumber * 4))
/* --- DCTRL Register ---*/
/* Alias word address of DMAEN bit */
#define DCTRL_OFFSET (SDIO_OFFSET + 0x2C)
#define DMAEN_BitNumber 0x03
#define DCTRL_DMAEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (DMAEN_BitNumber * 4))
/* Alias word address of RWSTART bit */
#define RWSTART_BitNumber 0x08
#define DCTRL_RWSTART_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTART_BitNumber * 4))
/* Alias word address of RWSTOP bit */
#define RWSTOP_BitNumber 0x09
#define DCTRL_RWSTOP_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWSTOP_BitNumber * 4))
/* Alias word address of RWMOD bit */
#define RWMOD_BitNumber 0x0A
#define DCTRL_RWMOD_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (RWMOD_BitNumber * 4))
/* Alias word address of SDIOEN bit */
#define SDIOEN_BitNumber 0x0B
#define DCTRL_SDIOEN_BB (PERIPH_BB_BASE + (DCTRL_OFFSET * 32) + (SDIOEN_BitNumber * 4))
/* ---------------------- SDIO registers bit mask ------------------------ */
/* --- CLKCR Register ---*/
/* CLKCR register clear mask */
#define CLKCR_CLEAR_MASK ((uint32_t)0xFFFF8100)
/* --- PWRCTRL Register ---*/
/* SDIO PWRCTRL Mask */
#define PWR_PWRCTRL_MASK ((uint32_t)0xFFFFFFFC)
/* --- DCTRL Register ---*/
/* SDIO DCTRL Clear Mask */
#define DCTRL_CLEAR_MASK ((uint32_t)0xFFFFFF08)
/* --- CMD Register ---*/
/* CMD Register clear mask */
#define CMD_CLEAR_MASK ((uint32_t)0xFFFFF800)
/* SDIO RESP Registers Address */
#define SDIO_RESP_ADDR ((uint32_t)(SDIO_BASE + 0x14))
/**
* @}
*/
/** @defgroup SDIO_Private_Defines
* @{
*/
/**
* @}
*/
/** @defgroup SDIO_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup SDIO_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup SDIO_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup SDIO_Private_Functions
* @{
*/
/**
* @brief Deinitializes the SDIO peripheral registers to their default reset values.
* @param None
* @retval None
*/
void SDIO_DeInit(void)
{
SDIO->POWER = 0x00000000;
SDIO->CLKCR = 0x00000000;
SDIO->ARG = 0x00000000;
SDIO->CMD = 0x00000000;
SDIO->DTIMER = 0x00000000;
SDIO->DLEN = 0x00000000;
SDIO->DCTRL = 0x00000000;
SDIO->ICR = 0x00C007FF;
SDIO->MASK = 0x00000000;
}
/**
* @brief Initializes the SDIO peripheral according to the specified
* parameters in the SDIO_InitStruct.
* @param SDIO_InitStruct : pointer to a SDIO_InitTypeDef structure
* that contains the configuration information for the SDIO peripheral.
* @retval None
*/
void SDIO_Init(SDIO_InitTypeDef* SDIO_InitStruct)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_SDIO_CLOCK_EDGE(SDIO_InitStruct->SDIO_ClockEdge));
assert_param(IS_SDIO_CLOCK_BYPASS(SDIO_InitStruct->SDIO_ClockBypass));
assert_param(IS_SDIO_CLOCK_POWER_SAVE(SDIO_InitStruct->SDIO_ClockPowerSave));
assert_param(IS_SDIO_BUS_WIDE(SDIO_InitStruct->SDIO_BusWide));
assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(SDIO_InitStruct->SDIO_HardwareFlowControl));
/*---------------------------- SDIO CLKCR Configuration ------------------------*/
/* Get the SDIO CLKCR value */
tmpreg = SDIO->CLKCR;
/* Clear CLKDIV, PWRSAV, BYPASS, WIDBUS, NEGEDGE, HWFC_EN bits */
tmpreg &= CLKCR_CLEAR_MASK;
/* Set CLKDIV bits according to SDIO_ClockDiv value */
/* Set PWRSAV bit according to SDIO_ClockPowerSave value */
/* Set BYPASS bit according to SDIO_ClockBypass value */
/* Set WIDBUS bits according to SDIO_BusWide value */
/* Set NEGEDGE bits according to SDIO_ClockEdge value */
/* Set HWFC_EN bits according to SDIO_HardwareFlowControl value */
tmpreg |= (SDIO_InitStruct->SDIO_ClockDiv | SDIO_InitStruct->SDIO_ClockPowerSave |
SDIO_InitStruct->SDIO_ClockBypass | SDIO_InitStruct->SDIO_BusWide |
SDIO_InitStruct->SDIO_ClockEdge | SDIO_InitStruct->SDIO_HardwareFlowControl);
/* Write to SDIO CLKCR */
SDIO->CLKCR = tmpreg;
}
/**
* @brief Fills each SDIO_InitStruct member with its default value.
* @param SDIO_InitStruct: pointer to an SDIO_InitTypeDef structure which
* will be initialized.
* @retval None
*/
void SDIO_StructInit(SDIO_InitTypeDef* SDIO_InitStruct)
{
/* SDIO_InitStruct members default value */
SDIO_InitStruct->SDIO_ClockDiv = 0x00;
SDIO_InitStruct->SDIO_ClockEdge = SDIO_ClockEdge_Rising;
SDIO_InitStruct->SDIO_ClockBypass = SDIO_ClockBypass_Disable;
SDIO_InitStruct->SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
SDIO_InitStruct->SDIO_BusWide = SDIO_BusWide_1b;
SDIO_InitStruct->SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
}
/**
* @brief Enables or disables the SDIO Clock.
* @param NewState: new state of the SDIO Clock. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_ClockCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CLKCR_CLKEN_BB = (uint32_t)NewState;
}
/**
* @brief Sets the power status of the controller.
* @param SDIO_PowerState: new state of the Power state.
* This parameter can be one of the following values:
* @arg SDIO_PowerState_OFF
* @arg SDIO_PowerState_ON
* @retval None
*/
void SDIO_SetPowerState(uint32_t SDIO_PowerState)
{
/* Check the parameters */
assert_param(IS_SDIO_POWER_STATE(SDIO_PowerState));
SDIO->POWER &= PWR_PWRCTRL_MASK;
SDIO->POWER |= SDIO_PowerState;
}
/**
* @brief Gets the power status of the controller.
* @param None
* @retval Power status of the controller. The returned value can
* be one of the following:
* - 0x00: Power OFF
* - 0x02: Power UP
* - 0x03: Power ON
*/
uint32_t SDIO_GetPowerState(void)
{
return (SDIO->POWER & (~PWR_PWRCTRL_MASK));
}
/**
* @brief Enables or disables the SDIO interrupts.
* @param SDIO_IT: specifies the SDIO interrupt sources to be enabled or disabled.
* This parameter can be one or a combination of the following values:
* @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDIO_IT_DTIMEOUT: Data timeout interrupt
* @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt
* @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide
* bus mode interrupt
* @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt
* @arg SDIO_IT_CMDACT: Command transfer in progress interrupt
* @arg SDIO_IT_TXACT: Data transmit in progress interrupt
* @arg SDIO_IT_RXACT: Data receive in progress interrupt
* @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt
* @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt
* @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt
* @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt
* @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt
* @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt
* @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt
* @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt
* @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt
* @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt
* @param NewState: new state of the specified SDIO interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_ITConfig(uint32_t SDIO_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_SDIO_IT(SDIO_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the SDIO interrupts */
SDIO->MASK |= SDIO_IT;
}
else
{
/* Disable the SDIO interrupts */
SDIO->MASK &= ~SDIO_IT;
}
}
/**
* @brief Enables or disables the SDIO DMA request.
* @param NewState: new state of the selected SDIO DMA request.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_DMACmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) DCTRL_DMAEN_BB = (uint32_t)NewState;
}
/**
* @brief Initializes the SDIO Command according to the specified
* parameters in the SDIO_CmdInitStruct and send the command.
* @param SDIO_CmdInitStruct : pointer to a SDIO_CmdInitTypeDef
* structure that contains the configuration information for the SDIO command.
* @retval None
*/
void SDIO_SendCommand(SDIO_CmdInitTypeDef *SDIO_CmdInitStruct)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_SDIO_CMD_INDEX(SDIO_CmdInitStruct->SDIO_CmdIndex));
assert_param(IS_SDIO_RESPONSE(SDIO_CmdInitStruct->SDIO_Response));
assert_param(IS_SDIO_WAIT(SDIO_CmdInitStruct->SDIO_Wait));
assert_param(IS_SDIO_CPSM(SDIO_CmdInitStruct->SDIO_CPSM));
/*---------------------------- SDIO ARG Configuration ------------------------*/
/* Set the SDIO Argument value */
SDIO->ARG = SDIO_CmdInitStruct->SDIO_Argument;
/*---------------------------- SDIO CMD Configuration ------------------------*/
/* Get the SDIO CMD value */
tmpreg = SDIO->CMD;
/* Clear CMDINDEX, WAITRESP, WAITINT, WAITPEND, CPSMEN bits */
tmpreg &= CMD_CLEAR_MASK;
/* Set CMDINDEX bits according to SDIO_CmdIndex value */
/* Set WAITRESP bits according to SDIO_Response value */
/* Set WAITINT and WAITPEND bits according to SDIO_Wait value */
/* Set CPSMEN bits according to SDIO_CPSM value */
tmpreg |= (uint32_t)SDIO_CmdInitStruct->SDIO_CmdIndex | SDIO_CmdInitStruct->SDIO_Response
| SDIO_CmdInitStruct->SDIO_Wait | SDIO_CmdInitStruct->SDIO_CPSM;
/* Write to SDIO CMD */
SDIO->CMD = tmpreg;
}
/**
* @brief Fills each SDIO_CmdInitStruct member with its default value.
* @param SDIO_CmdInitStruct: pointer to an SDIO_CmdInitTypeDef
* structure which will be initialized.
* @retval None
*/
void SDIO_CmdStructInit(SDIO_CmdInitTypeDef* SDIO_CmdInitStruct)
{
/* SDIO_CmdInitStruct members default value */
SDIO_CmdInitStruct->SDIO_Argument = 0x00;
SDIO_CmdInitStruct->SDIO_CmdIndex = 0x00;
SDIO_CmdInitStruct->SDIO_Response = SDIO_Response_No;
SDIO_CmdInitStruct->SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStruct->SDIO_CPSM = SDIO_CPSM_Disable;
}
/**
* @brief Returns command index of last command for which response received.
* @param None
* @retval Returns the command index of the last command response received.
*/
uint8_t SDIO_GetCommandResponse(void)
{
return (uint8_t)(SDIO->RESPCMD);
}
/**
* @brief Returns response received from the card for the last command.
* @param SDIO_RESP: Specifies the SDIO response register.
* This parameter can be one of the following values:
* @arg SDIO_RESP1: Response Register 1
* @arg SDIO_RESP2: Response Register 2
* @arg SDIO_RESP3: Response Register 3
* @arg SDIO_RESP4: Response Register 4
* @retval The Corresponding response register value.
*/
uint32_t SDIO_GetResponse(uint32_t SDIO_RESP)
{
__IO uint32_t tmp = 0;
/* Check the parameters */
assert_param(IS_SDIO_RESP(SDIO_RESP));
tmp = SDIO_RESP_ADDR + SDIO_RESP;
return (*(__IO uint32_t *) tmp);
}
/**
* @brief Initializes the SDIO data path according to the specified
* parameters in the SDIO_DataInitStruct.
* @param SDIO_DataInitStruct : pointer to a SDIO_DataInitTypeDef structure that
* contains the configuration information for the SDIO command.
* @retval None
*/
void SDIO_DataConfig(SDIO_DataInitTypeDef* SDIO_DataInitStruct)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_SDIO_DATA_LENGTH(SDIO_DataInitStruct->SDIO_DataLength));
assert_param(IS_SDIO_BLOCK_SIZE(SDIO_DataInitStruct->SDIO_DataBlockSize));
assert_param(IS_SDIO_TRANSFER_DIR(SDIO_DataInitStruct->SDIO_TransferDir));
assert_param(IS_SDIO_TRANSFER_MODE(SDIO_DataInitStruct->SDIO_TransferMode));
assert_param(IS_SDIO_DPSM(SDIO_DataInitStruct->SDIO_DPSM));
/*---------------------------- SDIO DTIMER Configuration ---------------------*/
/* Set the SDIO Data TimeOut value */
SDIO->DTIMER = SDIO_DataInitStruct->SDIO_DataTimeOut;
/*---------------------------- SDIO DLEN Configuration -----------------------*/
/* Set the SDIO DataLength value */
SDIO->DLEN = SDIO_DataInitStruct->SDIO_DataLength;
/*---------------------------- SDIO DCTRL Configuration ----------------------*/
/* Get the SDIO DCTRL value */
tmpreg = SDIO->DCTRL;
/* Clear DEN, DTMODE, DTDIR and DBCKSIZE bits */
tmpreg &= DCTRL_CLEAR_MASK;
/* Set DEN bit according to SDIO_DPSM value */
/* Set DTMODE bit according to SDIO_TransferMode value */
/* Set DTDIR bit according to SDIO_TransferDir value */
/* Set DBCKSIZE bits according to SDIO_DataBlockSize value */
tmpreg |= (uint32_t)SDIO_DataInitStruct->SDIO_DataBlockSize | SDIO_DataInitStruct->SDIO_TransferDir
| SDIO_DataInitStruct->SDIO_TransferMode | SDIO_DataInitStruct->SDIO_DPSM;
/* Write to SDIO DCTRL */
SDIO->DCTRL = tmpreg;
}
/**
* @brief Fills each SDIO_DataInitStruct member with its default value.
* @param SDIO_DataInitStruct: pointer to an SDIO_DataInitTypeDef structure which
* will be initialized.
* @retval None
*/
void SDIO_DataStructInit(SDIO_DataInitTypeDef* SDIO_DataInitStruct)
{
/* SDIO_DataInitStruct members default value */
SDIO_DataInitStruct->SDIO_DataTimeOut = 0xFFFFFFFF;
SDIO_DataInitStruct->SDIO_DataLength = 0x00;
SDIO_DataInitStruct->SDIO_DataBlockSize = SDIO_DataBlockSize_1b;
SDIO_DataInitStruct->SDIO_TransferDir = SDIO_TransferDir_ToCard;
SDIO_DataInitStruct->SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataInitStruct->SDIO_DPSM = SDIO_DPSM_Disable;
}
/**
* @brief Returns number of remaining data bytes to be transferred.
* @param None
* @retval Number of remaining data bytes to be transferred
*/
uint32_t SDIO_GetDataCounter(void)
{
return SDIO->DCOUNT;
}
/**
* @brief Read one data word from Rx FIFO.
* @param None
* @retval Data received
*/
uint32_t SDIO_ReadData(void)
{
return SDIO->FIFO;
}
/**
* @brief Write one data word to Tx FIFO.
* @param Data: 32-bit data word to write.
* @retval None
*/
void SDIO_WriteData(uint32_t Data)
{
SDIO->FIFO = Data;
}
/**
* @brief Returns the number of words left to be written to or read from FIFO.
* @param None
* @retval Remaining number of words.
*/
uint32_t SDIO_GetFIFOCount(void)
{
return SDIO->FIFOCNT;
}
/**
* @brief Starts the SD I/O Read Wait operation.
* @param NewState: new state of the Start SDIO Read Wait operation.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_StartSDIOReadWait(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) DCTRL_RWSTART_BB = (uint32_t) NewState;
}
/**
* @brief Stops the SD I/O Read Wait operation.
* @param NewState: new state of the Stop SDIO Read Wait operation.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_StopSDIOReadWait(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) DCTRL_RWSTOP_BB = (uint32_t) NewState;
}
/**
* @brief Sets one of the two options of inserting read wait interval.
* @param SDIO_ReadWaitMode: SD I/O Read Wait operation mode.
* This parameter can be:
* @arg SDIO_ReadWaitMode_CLK: Read Wait control by stopping SDIOCLK
* @arg SDIO_ReadWaitMode_DATA2: Read Wait control using SDIO_DATA2
* @retval None
*/
void SDIO_SetSDIOReadWaitMode(uint32_t SDIO_ReadWaitMode)
{
/* Check the parameters */
assert_param(IS_SDIO_READWAIT_MODE(SDIO_ReadWaitMode));
*(__IO uint32_t *) DCTRL_RWMOD_BB = SDIO_ReadWaitMode;
}
/**
* @brief Enables or disables the SD I/O Mode Operation.
* @param NewState: new state of SDIO specific operation.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_SetSDIOOperation(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) DCTRL_SDIOEN_BB = (uint32_t)NewState;
}
/**
* @brief Enables or disables the SD I/O Mode suspend command sending.
* @param NewState: new state of the SD I/O Mode suspend command.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_SendSDIOSuspendCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CMD_SDIOSUSPEND_BB = (uint32_t)NewState;
}
/**
* @brief Enables or disables the command completion signal.
* @param NewState: new state of command completion signal.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_CommandCompletionCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CMD_ENCMDCOMPL_BB = (uint32_t)NewState;
}
/**
* @brief Enables or disables the CE-ATA interrupt.
* @param NewState: new state of CE-ATA interrupt. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_CEATAITCmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CMD_NIEN_BB = (uint32_t)((~((uint32_t)NewState)) & ((uint32_t)0x1));
}
/**
* @brief Sends CE-ATA command (CMD61).
* @param NewState: new state of CE-ATA command. This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SDIO_SendCEATACmd(FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_FUNCTIONAL_STATE(NewState));
*(__IO uint32_t *) CMD_ATACMD_BB = (uint32_t)NewState;
}
/**
* @brief Checks whether the specified SDIO flag is set or not.
* @param SDIO_FLAG: specifies the flag to check.
* This parameter can be one of the following values:
* @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed)
* @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed)
* @arg SDIO_FLAG_CTIMEOUT: Command response timeout
* @arg SDIO_FLAG_DTIMEOUT: Data timeout
* @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error
* @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error
* @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed)
* @arg SDIO_FLAG_CMDSENT: Command sent (no response required)
* @arg SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero)
* @arg SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide
* bus mode.
* @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed)
* @arg SDIO_FLAG_CMDACT: Command transfer in progress
* @arg SDIO_FLAG_TXACT: Data transmit in progress
* @arg SDIO_FLAG_RXACT: Data receive in progress
* @arg SDIO_FLAG_TXFIFOHE: Transmit FIFO Half Empty
* @arg SDIO_FLAG_RXFIFOHF: Receive FIFO Half Full
* @arg SDIO_FLAG_TXFIFOF: Transmit FIFO full
* @arg SDIO_FLAG_RXFIFOF: Receive FIFO full
* @arg SDIO_FLAG_TXFIFOE: Transmit FIFO empty
* @arg SDIO_FLAG_RXFIFOE: Receive FIFO empty
* @arg SDIO_FLAG_TXDAVL: Data available in transmit FIFO
* @arg SDIO_FLAG_RXDAVL: Data available in receive FIFO
* @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received
* @arg SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61
* @retval The new state of SDIO_FLAG (SET or RESET).
*/
FlagStatus SDIO_GetFlagStatus(uint32_t SDIO_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_SDIO_FLAG(SDIO_FLAG));
if ((SDIO->STA & SDIO_FLAG) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the SDIO's pending flags.
* @param SDIO_FLAG: specifies the flag to clear.
* This parameter can be one or a combination of the following values:
* @arg SDIO_FLAG_CCRCFAIL: Command response received (CRC check failed)
* @arg SDIO_FLAG_DCRCFAIL: Data block sent/received (CRC check failed)
* @arg SDIO_FLAG_CTIMEOUT: Command response timeout
* @arg SDIO_FLAG_DTIMEOUT: Data timeout
* @arg SDIO_FLAG_TXUNDERR: Transmit FIFO underrun error
* @arg SDIO_FLAG_RXOVERR: Received FIFO overrun error
* @arg SDIO_FLAG_CMDREND: Command response received (CRC check passed)
* @arg SDIO_FLAG_CMDSENT: Command sent (no response required)
* @arg SDIO_FLAG_DATAEND: Data end (data counter, SDIDCOUNT, is zero)
* @arg SDIO_FLAG_STBITERR: Start bit not detected on all data signals in wide
* bus mode
* @arg SDIO_FLAG_DBCKEND: Data block sent/received (CRC check passed)
* @arg SDIO_FLAG_SDIOIT: SD I/O interrupt received
* @arg SDIO_FLAG_CEATAEND: CE-ATA command completion signal received for CMD61
* @retval None
*/
void SDIO_ClearFlag(uint32_t SDIO_FLAG)
{
/* Check the parameters */
assert_param(IS_SDIO_CLEAR_FLAG(SDIO_FLAG));
SDIO->ICR = SDIO_FLAG;
}
/**
* @brief Checks whether the specified SDIO interrupt has occurred or not.
* @param SDIO_IT: specifies the SDIO interrupt source to check.
* This parameter can be one of the following values:
* @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDIO_IT_DTIMEOUT: Data timeout interrupt
* @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt
* @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide
* bus mode interrupt
* @arg SDIO_IT_DBCKEND: Data block sent/received (CRC check passed) interrupt
* @arg SDIO_IT_CMDACT: Command transfer in progress interrupt
* @arg SDIO_IT_TXACT: Data transmit in progress interrupt
* @arg SDIO_IT_RXACT: Data receive in progress interrupt
* @arg SDIO_IT_TXFIFOHE: Transmit FIFO Half Empty interrupt
* @arg SDIO_IT_RXFIFOHF: Receive FIFO Half Full interrupt
* @arg SDIO_IT_TXFIFOF: Transmit FIFO full interrupt
* @arg SDIO_IT_RXFIFOF: Receive FIFO full interrupt
* @arg SDIO_IT_TXFIFOE: Transmit FIFO empty interrupt
* @arg SDIO_IT_RXFIFOE: Receive FIFO empty interrupt
* @arg SDIO_IT_TXDAVL: Data available in transmit FIFO interrupt
* @arg SDIO_IT_RXDAVL: Data available in receive FIFO interrupt
* @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt
* @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61 interrupt
* @retval The new state of SDIO_IT (SET or RESET).
*/
ITStatus SDIO_GetITStatus(uint32_t SDIO_IT)
{
ITStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_SDIO_GET_IT(SDIO_IT));
if ((SDIO->STA & SDIO_IT) != (uint32_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the SDIO's interrupt pending bits.
* @param SDIO_IT: specifies the interrupt pending bit to clear.
* This parameter can be one or a combination of the following values:
* @arg SDIO_IT_CCRCFAIL: Command response received (CRC check failed) interrupt
* @arg SDIO_IT_DCRCFAIL: Data block sent/received (CRC check failed) interrupt
* @arg SDIO_IT_CTIMEOUT: Command response timeout interrupt
* @arg SDIO_IT_DTIMEOUT: Data timeout interrupt
* @arg SDIO_IT_TXUNDERR: Transmit FIFO underrun error interrupt
* @arg SDIO_IT_RXOVERR: Received FIFO overrun error interrupt
* @arg SDIO_IT_CMDREND: Command response received (CRC check passed) interrupt
* @arg SDIO_IT_CMDSENT: Command sent (no response required) interrupt
* @arg SDIO_IT_DATAEND: Data end (data counter, SDIDCOUNT, is zero) interrupt
* @arg SDIO_IT_STBITERR: Start bit not detected on all data signals in wide
* bus mode interrupt
* @arg SDIO_IT_SDIOIT: SD I/O interrupt received interrupt
* @arg SDIO_IT_CEATAEND: CE-ATA command completion signal received for CMD61
* @retval None
*/
void SDIO_ClearITPendingBit(uint32_t SDIO_IT)
{
/* Check the parameters */
assert_param(IS_SDIO_CLEAR_IT(SDIO_IT));
SDIO->ICR = SDIO_IT;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_spi.c
================================================
/**
******************************************************************************
* @file stm32f10x_spi.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the SPI firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_spi.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup SPI
* @brief SPI driver modules
* @{
*/
/** @defgroup SPI_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup SPI_Private_Defines
* @{
*/
/* SPI SPE mask */
#define CR1_SPE_Set ((uint16_t)0x0040)
#define CR1_SPE_Reset ((uint16_t)0xFFBF)
/* I2S I2SE mask */
#define I2SCFGR_I2SE_Set ((uint16_t)0x0400)
#define I2SCFGR_I2SE_Reset ((uint16_t)0xFBFF)
/* SPI CRCNext mask */
#define CR1_CRCNext_Set ((uint16_t)0x1000)
/* SPI CRCEN mask */
#define CR1_CRCEN_Set ((uint16_t)0x2000)
#define CR1_CRCEN_Reset ((uint16_t)0xDFFF)
/* SPI SSOE mask */
#define CR2_SSOE_Set ((uint16_t)0x0004)
#define CR2_SSOE_Reset ((uint16_t)0xFFFB)
/* SPI registers Masks */
#define CR1_CLEAR_Mask ((uint16_t)0x3040)
#define I2SCFGR_CLEAR_Mask ((uint16_t)0xF040)
/* SPI or I2S mode selection masks */
#define SPI_Mode_Select ((uint16_t)0xF7FF)
#define I2S_Mode_Select ((uint16_t)0x0800)
/* I2S clock source selection masks */
#define I2S2_CLOCK_SRC ((uint32_t)(0x00020000))
#define I2S3_CLOCK_SRC ((uint32_t)(0x00040000))
#define I2S_MUL_MASK ((uint32_t)(0x0000F000))
#define I2S_DIV_MASK ((uint32_t)(0x000000F0))
/**
* @}
*/
/** @defgroup SPI_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup SPI_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup SPI_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup SPI_Private_Functions
* @{
*/
/**
* @brief Deinitializes the SPIx peripheral registers to their default
* reset values (Affects also the I2Ss).
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @retval None
*/
void SPI_I2S_DeInit(SPI_TypeDef* SPIx)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
if (SPIx == SPI1)
{
/* Enable SPI1 reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
/* Release SPI1 from reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);
}
else if (SPIx == SPI2)
{
/* Enable SPI2 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
/* Release SPI2 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);
}
else
{
if (SPIx == SPI3)
{
/* Enable SPI3 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE);
/* Release SPI3 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, DISABLE);
}
}
}
/**
* @brief Initializes the SPIx peripheral according to the specified
* parameters in the SPI_InitStruct.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @param SPI_InitStruct: pointer to a SPI_InitTypeDef structure that
* contains the configuration information for the specified SPI peripheral.
* @retval None
*/
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
{
uint16_t tmpreg = 0;
/* check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
/* Check the SPI parameters */
assert_param(IS_SPI_DIRECTION_MODE(SPI_InitStruct->SPI_Direction));
assert_param(IS_SPI_MODE(SPI_InitStruct->SPI_Mode));
assert_param(IS_SPI_DATASIZE(SPI_InitStruct->SPI_DataSize));
assert_param(IS_SPI_CPOL(SPI_InitStruct->SPI_CPOL));
assert_param(IS_SPI_CPHA(SPI_InitStruct->SPI_CPHA));
assert_param(IS_SPI_NSS(SPI_InitStruct->SPI_NSS));
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_InitStruct->SPI_BaudRatePrescaler));
assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->SPI_FirstBit));
assert_param(IS_SPI_CRC_POLYNOMIAL(SPI_InitStruct->SPI_CRCPolynomial));
/*---------------------------- SPIx CR1 Configuration ------------------------*/
/* Get the SPIx CR1 value */
tmpreg = SPIx->CR1;
/* Clear BIDIMode, BIDIOE, RxONLY, SSM, SSI, LSBFirst, BR, MSTR, CPOL and CPHA bits */
tmpreg &= CR1_CLEAR_Mask;
/* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler
master/salve mode, CPOL and CPHA */
/* Set BIDImode, BIDIOE and RxONLY bits according to SPI_Direction value */
/* Set SSM, SSI and MSTR bits according to SPI_Mode and SPI_NSS values */
/* Set LSBFirst bit according to SPI_FirstBit value */
/* Set BR bits according to SPI_BaudRatePrescaler value */
/* Set CPOL bit according to SPI_CPOL value */
/* Set CPHA bit according to SPI_CPHA value */
tmpreg |= (uint16_t)((uint32_t)SPI_InitStruct->SPI_Direction | SPI_InitStruct->SPI_Mode |
SPI_InitStruct->SPI_DataSize | SPI_InitStruct->SPI_CPOL |
SPI_InitStruct->SPI_CPHA | SPI_InitStruct->SPI_NSS |
SPI_InitStruct->SPI_BaudRatePrescaler | SPI_InitStruct->SPI_FirstBit);
/* Write to SPIx CR1 */
SPIx->CR1 = tmpreg;
/* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */
SPIx->I2SCFGR &= SPI_Mode_Select;
/*---------------------------- SPIx CRCPOLY Configuration --------------------*/
/* Write to SPIx CRCPOLY */
SPIx->CRCPR = SPI_InitStruct->SPI_CRCPolynomial;
}
/**
* @brief Initializes the SPIx peripheral according to the specified
* parameters in the I2S_InitStruct.
* @param SPIx: where x can be 2 or 3 to select the SPI peripheral
* (configured in I2S mode).
* @param I2S_InitStruct: pointer to an I2S_InitTypeDef structure that
* contains the configuration information for the specified SPI peripheral
* configured in I2S mode.
* @note
* The function calculates the optimal prescaler needed to obtain the most
* accurate audio frequency (depending on the I2S clock source, the PLL values
* and the product configuration). But in case the prescaler value is greater
* than 511, the default value (0x02) will be configured instead. *
* @retval None
*/
void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct)
{
uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1;
uint32_t tmp = 0;
RCC_ClocksTypeDef RCC_Clocks;
uint32_t sourceclock = 0;
/* Check the I2S parameters */
assert_param(IS_SPI_23_PERIPH(SPIx));
assert_param(IS_I2S_MODE(I2S_InitStruct->I2S_Mode));
assert_param(IS_I2S_STANDARD(I2S_InitStruct->I2S_Standard));
assert_param(IS_I2S_DATA_FORMAT(I2S_InitStruct->I2S_DataFormat));
assert_param(IS_I2S_MCLK_OUTPUT(I2S_InitStruct->I2S_MCLKOutput));
assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->I2S_AudioFreq));
assert_param(IS_I2S_CPOL(I2S_InitStruct->I2S_CPOL));
/*----------------------- SPIx I2SCFGR & I2SPR Configuration -----------------*/
/* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */
SPIx->I2SCFGR &= I2SCFGR_CLEAR_Mask;
SPIx->I2SPR = 0x0002;
/* Get the I2SCFGR register value */
tmpreg = SPIx->I2SCFGR;
/* If the default value has to be written, reinitialize i2sdiv and i2sodd*/
if(I2S_InitStruct->I2S_AudioFreq == I2S_AudioFreq_Default)
{
i2sodd = (uint16_t)0;
i2sdiv = (uint16_t)2;
}
/* If the requested audio frequency is not the default, compute the prescaler */
else
{
/* Check the frame length (For the Prescaler computing) */
if(I2S_InitStruct->I2S_DataFormat == I2S_DataFormat_16b)
{
/* Packet length is 16 bits */
packetlength = 1;
}
else
{
/* Packet length is 32 bits */
packetlength = 2;
}
/* Get the I2S clock source mask depending on the peripheral number */
if(((uint32_t)SPIx) == SPI2_BASE)
{
/* The mask is relative to I2S2 */
tmp = I2S2_CLOCK_SRC;
}
else
{
/* The mask is relative to I2S3 */
tmp = I2S3_CLOCK_SRC;
}
/* Check the I2S clock source configuration depending on the Device:
Only Connectivity line devices have the PLL3 VCO clock */
#ifdef STM32F10X_CL
if((RCC->CFGR2 & tmp) != 0)
{
/* Get the configuration bits of RCC PLL3 multiplier */
tmp = (uint32_t)((RCC->CFGR2 & I2S_MUL_MASK) >> 12);
/* Get the value of the PLL3 multiplier */
if((tmp > 5) && (tmp < 15))
{
/* Multiplier is between 8 and 14 (value 15 is forbidden) */
tmp += 2;
}
else
{
if (tmp == 15)
{
/* Multiplier is 20 */
tmp = 20;
}
}
/* Get the PREDIV2 value */
sourceclock = (uint32_t)(((RCC->CFGR2 & I2S_DIV_MASK) >> 4) + 1);
/* Calculate the Source Clock frequency based on PLL3 and PREDIV2 values */
sourceclock = (uint32_t) ((HSE_Value / sourceclock) * tmp * 2);
}
else
{
/* I2S Clock source is System clock: Get System Clock frequency */
RCC_GetClocksFreq(&RCC_Clocks);
/* Get the source clock value: based on System Clock value */
sourceclock = RCC_Clocks.SYSCLK_Frequency;
}
#else /* STM32F10X_HD */
/* I2S Clock source is System clock: Get System Clock frequency */
RCC_GetClocksFreq(&RCC_Clocks);
/* Get the source clock value: based on System Clock value */
sourceclock = RCC_Clocks.SYSCLK_Frequency;
#endif /* STM32F10X_CL */
/* Compute the Real divider depending on the MCLK output state with a floating point */
if(I2S_InitStruct->I2S_MCLKOutput == I2S_MCLKOutput_Enable)
{
/* MCLK output is enabled */
tmp = (uint16_t)(((((sourceclock / 256) * 10) / I2S_InitStruct->I2S_AudioFreq)) + 5);
}
else
{
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsign-conversion"
#endif
/* MCLK output is disabled */
tmp = (uint16_t)(((((sourceclock / (32 * packetlength)) *10 ) / I2S_InitStruct->I2S_AudioFreq)) + 5);
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
}
/* Remove the floating point */
tmp = tmp / 10;
/* Check the parity of the divider */
i2sodd = (uint16_t)(tmp & (uint16_t)0x0001);
/* Compute the i2sdiv prescaler */
i2sdiv = (uint16_t)((tmp - i2sodd) / 2);
/* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */
i2sodd = (uint16_t) (i2sodd << 8);
}
/* Test if the divider is 1 or 0 or greater than 0xFF */
if ((i2sdiv < 2) || (i2sdiv > 0xFF))
{
/* Set the default values */
i2sdiv = 2;
i2sodd = 0;
}
/* Write to SPIx I2SPR register the computed value */
SPIx->I2SPR = (uint16_t)(i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->I2S_MCLKOutput));
/* Configure the I2S with the SPI_InitStruct values */
tmpreg |= (uint16_t)(I2S_Mode_Select | (uint16_t)(I2S_InitStruct->I2S_Mode | \
(uint16_t)(I2S_InitStruct->I2S_Standard | (uint16_t)(I2S_InitStruct->I2S_DataFormat | \
(uint16_t)I2S_InitStruct->I2S_CPOL))));
/* Write to SPIx I2SCFGR */
SPIx->I2SCFGR = tmpreg;
}
/**
* @brief Fills each SPI_InitStruct member with its default value.
* @param SPI_InitStruct : pointer to a SPI_InitTypeDef structure which will be initialized.
* @retval None
*/
void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct)
{
/*--------------- Reset SPI init structure parameters values -----------------*/
/* Initialize the SPI_Direction member */
SPI_InitStruct->SPI_Direction = SPI_Direction_2Lines_FullDuplex;
/* initialize the SPI_Mode member */
SPI_InitStruct->SPI_Mode = SPI_Mode_Slave;
/* initialize the SPI_DataSize member */
SPI_InitStruct->SPI_DataSize = SPI_DataSize_8b;
/* Initialize the SPI_CPOL member */
SPI_InitStruct->SPI_CPOL = SPI_CPOL_Low;
/* Initialize the SPI_CPHA member */
SPI_InitStruct->SPI_CPHA = SPI_CPHA_1Edge;
/* Initialize the SPI_NSS member */
SPI_InitStruct->SPI_NSS = SPI_NSS_Hard;
/* Initialize the SPI_BaudRatePrescaler member */
SPI_InitStruct->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
/* Initialize the SPI_FirstBit member */
SPI_InitStruct->SPI_FirstBit = SPI_FirstBit_MSB;
/* Initialize the SPI_CRCPolynomial member */
SPI_InitStruct->SPI_CRCPolynomial = 7;
}
/**
* @brief Fills each I2S_InitStruct member with its default value.
* @param I2S_InitStruct : pointer to a I2S_InitTypeDef structure which will be initialized.
* @retval None
*/
void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct)
{
/*--------------- Reset I2S init structure parameters values -----------------*/
/* Initialize the I2S_Mode member */
I2S_InitStruct->I2S_Mode = I2S_Mode_SlaveTx;
/* Initialize the I2S_Standard member */
I2S_InitStruct->I2S_Standard = I2S_Standard_Phillips;
/* Initialize the I2S_DataFormat member */
I2S_InitStruct->I2S_DataFormat = I2S_DataFormat_16b;
/* Initialize the I2S_MCLKOutput member */
I2S_InitStruct->I2S_MCLKOutput = I2S_MCLKOutput_Disable;
/* Initialize the I2S_AudioFreq member */
I2S_InitStruct->I2S_AudioFreq = I2S_AudioFreq_Default;
/* Initialize the I2S_CPOL member */
I2S_InitStruct->I2S_CPOL = I2S_CPOL_Low;
}
/**
* @brief Enables or disables the specified SPI peripheral.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @param NewState: new state of the SPIx peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected SPI peripheral */
SPIx->CR1 |= CR1_SPE_Set;
}
else
{
/* Disable the selected SPI peripheral */
SPIx->CR1 &= CR1_SPE_Reset;
}
}
/**
* @brief Enables or disables the specified SPI peripheral (in I2S mode).
* @param SPIx: where x can be 2 or 3 to select the SPI peripheral.
* @param NewState: new state of the SPIx peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_SPI_23_PERIPH(SPIx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected SPI peripheral (in I2S mode) */
SPIx->I2SCFGR |= I2SCFGR_I2SE_Set;
}
else
{
/* Disable the selected SPI peripheral (in I2S mode) */
SPIx->I2SCFGR &= I2SCFGR_I2SE_Reset;
}
}
/**
* @brief Enables or disables the specified SPI/I2S interrupts.
* @param SPIx: where x can be
* - 1, 2 or 3 in SPI mode
* - 2 or 3 in I2S mode
* @param SPI_I2S_IT: specifies the SPI/I2S interrupt source to be enabled or disabled.
* This parameter can be one of the following values:
* @arg SPI_I2S_IT_TXE: Tx buffer empty interrupt mask
* @arg SPI_I2S_IT_RXNE: Rx buffer not empty interrupt mask
* @arg SPI_I2S_IT_ERR: Error interrupt mask
* @param NewState: new state of the specified SPI/I2S interrupt.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState)
{
uint16_t itpos = 0, itmask = 0 ;
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
assert_param(IS_SPI_I2S_CONFIG_IT(SPI_I2S_IT));
/* Get the SPI/I2S IT index */
itpos = SPI_I2S_IT >> 4;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/* Set the IT mask */
itmask = (uint16_t)1 << (uint16_t)itpos;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
if (NewState != DISABLE)
{
/* Enable the selected SPI/I2S interrupt */
SPIx->CR2 |= itmask;
}
else
{
/* Disable the selected SPI/I2S interrupt */
SPIx->CR2 &= (uint16_t)~itmask;
}
}
/**
* @brief Enables or disables the SPIx/I2Sx DMA interface.
* @param SPIx: where x can be
* - 1, 2 or 3 in SPI mode
* - 2 or 3 in I2S mode
* @param SPI_I2S_DMAReq: specifies the SPI/I2S DMA transfer request to be enabled or disabled.
* This parameter can be any combination of the following values:
* @arg SPI_I2S_DMAReq_Tx: Tx buffer DMA transfer request
* @arg SPI_I2S_DMAReq_Rx: Rx buffer DMA transfer request
* @param NewState: new state of the selected SPI/I2S DMA transfer request.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
assert_param(IS_SPI_I2S_DMAREQ(SPI_I2S_DMAReq));
if (NewState != DISABLE)
{
/* Enable the selected SPI/I2S DMA requests */
SPIx->CR2 |= SPI_I2S_DMAReq;
}
else
{
/* Disable the selected SPI/I2S DMA requests */
SPIx->CR2 &= (uint16_t)~SPI_I2S_DMAReq;
}
}
/**
* @brief Transmits a Data through the SPIx/I2Sx peripheral.
* @param SPIx: where x can be
* - 1, 2 or 3 in SPI mode
* - 2 or 3 in I2S mode
* @param Data : Data to be transmitted.
* @retval None
*/
void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
/* Write in the DR register the data to be sent */
SPIx->DR = Data;
}
/**
* @brief Returns the most recent received data by the SPIx/I2Sx peripheral.
* @param SPIx: where x can be
* - 1, 2 or 3 in SPI mode
* - 2 or 3 in I2S mode
* @retval The value of the received data.
*/
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
/* Return the data in the DR register */
return SPIx->DR;
}
/**
* @brief Configures internally by software the NSS pin for the selected SPI.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @param SPI_NSSInternalSoft: specifies the SPI NSS internal state.
* This parameter can be one of the following values:
* @arg SPI_NSSInternalSoft_Set: Set NSS pin internally
* @arg SPI_NSSInternalSoft_Reset: Reset NSS pin internally
* @retval None
*/
void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_SPI_NSS_INTERNAL(SPI_NSSInternalSoft));
if (SPI_NSSInternalSoft != SPI_NSSInternalSoft_Reset)
{
/* Set NSS pin internally by software */
SPIx->CR1 |= SPI_NSSInternalSoft_Set;
}
else
{
/* Reset NSS pin internally by software */
SPIx->CR1 &= SPI_NSSInternalSoft_Reset;
}
}
/**
* @brief Enables or disables the SS output for the selected SPI.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @param NewState: new state of the SPIx SS output.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected SPI SS output */
SPIx->CR2 |= CR2_SSOE_Set;
}
else
{
/* Disable the selected SPI SS output */
SPIx->CR2 &= CR2_SSOE_Reset;
}
}
/**
* @brief Configures the data size for the selected SPI.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @param SPI_DataSize: specifies the SPI data size.
* This parameter can be one of the following values:
* @arg SPI_DataSize_16b: Set data frame format to 16bit
* @arg SPI_DataSize_8b: Set data frame format to 8bit
* @retval None
*/
void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_SPI_DATASIZE(SPI_DataSize));
/* Clear DFF bit */
SPIx->CR1 &= (uint16_t)~SPI_DataSize_16b;
/* Set new DFF bit value */
SPIx->CR1 |= SPI_DataSize;
}
/**
* @brief Transmit the SPIx CRC value.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @retval None
*/
void SPI_TransmitCRC(SPI_TypeDef* SPIx)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
/* Enable the selected SPI CRC transmission */
SPIx->CR1 |= CR1_CRCNext_Set;
}
/**
* @brief Enables or disables the CRC value calculation of the transferred bytes.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @param NewState: new state of the SPIx CRC value calculation.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected SPI CRC calculation */
SPIx->CR1 |= CR1_CRCEN_Set;
}
else
{
/* Disable the selected SPI CRC calculation */
SPIx->CR1 &= CR1_CRCEN_Reset;
}
}
/**
* @brief Returns the transmit or the receive CRC register value for the specified SPI.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @param SPI_CRC: specifies the CRC register to be read.
* This parameter can be one of the following values:
* @arg SPI_CRC_Tx: Selects Tx CRC register
* @arg SPI_CRC_Rx: Selects Rx CRC register
* @retval The selected CRC register value..
*/
uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC)
{
uint16_t crcreg = 0;
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_SPI_CRC(SPI_CRC));
if (SPI_CRC != SPI_CRC_Rx)
{
/* Get the Tx CRC register */
crcreg = SPIx->TXCRCR;
}
else
{
/* Get the Rx CRC register */
crcreg = SPIx->RXCRCR;
}
/* Return the selected CRC register */
return crcreg;
}
/**
* @brief Returns the CRC Polynomial register value for the specified SPI.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @retval The CRC Polynomial register value.
*/
uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
/* Return the CRC polynomial register */
return SPIx->CRCPR;
}
/**
* @brief Selects the data transfer direction in bi-directional mode for the specified SPI.
* @param SPIx: where x can be 1, 2 or 3 to select the SPI peripheral.
* @param SPI_Direction: specifies the data transfer direction in bi-directional mode.
* This parameter can be one of the following values:
* @arg SPI_Direction_Tx: Selects Tx transmission direction
* @arg SPI_Direction_Rx: Selects Rx receive direction
* @retval None
*/
void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_SPI_DIRECTION(SPI_Direction));
if (SPI_Direction == SPI_Direction_Tx)
{
/* Set the Tx only mode */
SPIx->CR1 |= SPI_Direction_Tx;
}
else
{
/* Set the Rx only mode */
SPIx->CR1 &= SPI_Direction_Rx;
}
}
/**
* @brief Checks whether the specified SPI/I2S flag is set or not.
* @param SPIx: where x can be
* - 1, 2 or 3 in SPI mode
* - 2 or 3 in I2S mode
* @param SPI_I2S_FLAG: specifies the SPI/I2S flag to check.
* This parameter can be one of the following values:
* @arg SPI_I2S_FLAG_TXE: Transmit buffer empty flag.
* @arg SPI_I2S_FLAG_RXNE: Receive buffer not empty flag.
* @arg SPI_I2S_FLAG_BSY: Busy flag.
* @arg SPI_I2S_FLAG_OVR: Overrun flag.
* @arg SPI_FLAG_MODF: Mode Fault flag.
* @arg SPI_FLAG_CRCERR: CRC Error flag.
* @arg I2S_FLAG_UDR: Underrun Error flag.
* @arg I2S_FLAG_CHSIDE: Channel Side flag.
* @retval The new state of SPI_I2S_FLAG (SET or RESET).
*/
FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG));
/* Check the status of the specified SPI/I2S flag */
if ((SPIx->SR & SPI_I2S_FLAG) != (uint16_t)RESET)
{
/* SPI_I2S_FLAG is set */
bitstatus = SET;
}
else
{
/* SPI_I2S_FLAG is reset */
bitstatus = RESET;
}
/* Return the SPI_I2S_FLAG status */
return bitstatus;
}
/**
* @brief Clears the SPIx CRC Error (CRCERR) flag.
* @param SPIx: where x can be
* - 1, 2 or 3 in SPI mode
* @param SPI_I2S_FLAG: specifies the SPI flag to clear.
* This function clears only CRCERR flag.
* @note
* - OVR (OverRun error) flag is cleared by software sequence: a read
* operation to SPI_DR register (SPI_I2S_ReceiveData()) followed by a read
* operation to SPI_SR register (SPI_I2S_GetFlagStatus()).
* - UDR (UnderRun error) flag is cleared by a read operation to
* SPI_SR register (SPI_I2S_GetFlagStatus()).
* - MODF (Mode Fault) flag is cleared by software sequence: a read/write
* operation to SPI_SR register (SPI_I2S_GetFlagStatus()) followed by a
* write operation to SPI_CR1 register (SPI_Cmd() to enable the SPI).
* @retval None
*/
void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_SPI_I2S_CLEAR_FLAG(SPI_I2S_FLAG));
/* Clear the selected SPI CRC Error (CRCERR) flag */
SPIx->SR = (uint16_t)~SPI_I2S_FLAG;
}
/**
* @brief Checks whether the specified SPI/I2S interrupt has occurred or not.
* @param SPIx: where x can be
* - 1, 2 or 3 in SPI mode
* - 2 or 3 in I2S mode
* @param SPI_I2S_IT: specifies the SPI/I2S interrupt source to check.
* This parameter can be one of the following values:
* @arg SPI_I2S_IT_TXE: Transmit buffer empty interrupt.
* @arg SPI_I2S_IT_RXNE: Receive buffer not empty interrupt.
* @arg SPI_I2S_IT_OVR: Overrun interrupt.
* @arg SPI_IT_MODF: Mode Fault interrupt.
* @arg SPI_IT_CRCERR: CRC Error interrupt.
* @arg I2S_IT_UDR: Underrun Error interrupt.
* @retval The new state of SPI_I2S_IT (SET or RESET).
*/
ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT)
{
ITStatus bitstatus = RESET;
uint16_t itpos = 0, itmask = 0, enablestatus = 0;
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_SPI_I2S_GET_IT(SPI_I2S_IT));
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/* Get the SPI/I2S IT index */
itpos = (uint16_t)(0x01u << (SPI_I2S_IT & 0x0F));
/* Get the SPI/I2S IT mask */
itmask = SPI_I2S_IT >> 4;
/* Set the IT mask */
itmask = 0x01 << itmask;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/* Get the SPI_I2S_IT enable bit status */
enablestatus = (SPIx->CR2 & itmask) ;
/* Check the status of the specified SPI/I2S interrupt */
if (((SPIx->SR & itpos) != (uint16_t)RESET) && enablestatus)
{
/* SPI_I2S_IT is set */
bitstatus = SET;
}
else
{
/* SPI_I2S_IT is reset */
bitstatus = RESET;
}
/* Return the SPI_I2S_IT status */
return bitstatus;
}
/**
* @brief Clears the SPIx CRC Error (CRCERR) interrupt pending bit.
* @param SPIx: where x can be
* - 1, 2 or 3 in SPI mode
* @param SPI_I2S_IT: specifies the SPI interrupt pending bit to clear.
* This function clears only CRCERR interrupt pending bit.
* @note
* - OVR (OverRun Error) interrupt pending bit is cleared by software
* sequence: a read operation to SPI_DR register (SPI_I2S_ReceiveData())
* followed by a read operation to SPI_SR register (SPI_I2S_GetITStatus()).
* - UDR (UnderRun Error) interrupt pending bit is cleared by a read
* operation to SPI_SR register (SPI_I2S_GetITStatus()).
* - MODF (Mode Fault) interrupt pending bit is cleared by software sequence:
* a read/write operation to SPI_SR register (SPI_I2S_GetITStatus())
* followed by a write operation to SPI_CR1 register (SPI_Cmd() to enable
* the SPI).
* @retval None
*/
void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT)
{
uint16_t itpos = 0;
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_SPI_I2S_CLEAR_IT(SPI_I2S_IT));
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/* Get the SPI IT index */
itpos = (uint16_t)(0x01 << (SPI_I2S_IT & 0x0F));
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/* Clear the selected SPI CRC Error (CRCERR) interrupt pending bit */
SPIx->SR = (uint16_t)~itpos;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_tim.c
================================================
/**
******************************************************************************
* @file stm32f10x_tim.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the TIM firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_tim.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup TIM
* @brief TIM driver modules
* @{
*/
/** @defgroup TIM_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup TIM_Private_Defines
* @{
*/
/* ---------------------- TIM registers bit mask ------------------------ */
#define SMCR_ETR_Mask ((uint16_t)0x00FF)
#define CCMR_Offset ((uint16_t)0x0018)
#define CCER_CCE_Set ((uint16_t)0x0001)
#define CCER_CCNE_Set ((uint16_t)0x0004)
/**
* @}
*/
/** @defgroup TIM_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup TIM_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup TIM_Private_FunctionPrototypes
* @{
*/
static void TI1_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection,
uint16_t TIM_ICFilter);
static void TI2_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection,
uint16_t TIM_ICFilter);
static void TI3_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection,
uint16_t TIM_ICFilter);
static void TI4_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection,
uint16_t TIM_ICFilter);
/**
* @}
*/
/** @defgroup TIM_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup TIM_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup TIM_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup TIM_Private_Functions
* @{
*/
/**
* @brief Deinitializes the TIMx peripheral registers to their default reset values.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @retval None
*/
void TIM_DeInit(TIM_TypeDef* TIMx)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
if (TIMx == TIM1)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE);
}
else if (TIMx == TIM2)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, DISABLE);
}
else if (TIMx == TIM3)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE);
}
else if (TIMx == TIM4)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE);
}
else if (TIMx == TIM5)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE);
}
else if (TIMx == TIM6)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, DISABLE);
}
else if (TIMx == TIM7)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, DISABLE);
}
else if (TIMx == TIM8)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, DISABLE);
}
else if (TIMx == TIM9)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, DISABLE);
}
else if (TIMx == TIM10)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, DISABLE);
}
else if (TIMx == TIM11)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, DISABLE);
}
else if (TIMx == TIM12)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM12, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM12, DISABLE);
}
else if (TIMx == TIM13)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, DISABLE);
}
else if (TIMx == TIM14)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, DISABLE);
}
else if (TIMx == TIM15)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM15, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM15, DISABLE);
}
else if (TIMx == TIM16)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM16, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM16, DISABLE);
}
else
{
if (TIMx == TIM17)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM17, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM17, DISABLE);
}
}
}
/**
* @brief Initializes the TIMx Time Base Unit peripheral according to
* the specified parameters in the TIM_TimeBaseInitStruct.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param TIM_TimeBaseInitStruct: pointer to a TIM_TimeBaseInitTypeDef
* structure that contains the configuration information for the
* specified TIM peripheral.
* @retval None
*/
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{
uint16_t tmpcr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode));
assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision));
tmpcr1 = TIMx->CR1;
if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||
(TIMx == TIM4) || (TIMx == TIM5))
{
/* Select the Counter Mode */
tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;
}
if((TIMx != TIM6) && (TIMx != TIM7))
{
/* Set the clock division */
tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));
tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;
}
TIMx->CR1 = tmpcr1;
/* Set the Autoreload value */
TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;
/* Set the Prescaler value */
TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;
if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))
{
/* Set the Repetition Counter value */
TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter;
}
/* Generate an update event to reload the Prescaler and the Repetition counter
values immediately */
TIMx->EGR = TIM_PSCReloadMode_Immediate;
}
/**
* @brief Initializes the TIMx Channel1 according to the specified
* parameters in the TIM_OCInitStruct.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure
* that contains the configuration information for the specified TIM peripheral.
* @retval None
*/
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
{
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode));
assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState));
assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity));
/* Disable the Channel 1: Reset the CC1E Bit */
TIMx->CCER &= (uint16_t)(~(uint16_t)TIM_CCER_CC1E);
/* Get the TIMx CCER register value */
tmpccer = TIMx->CCER;
/* Get the TIMx CR2 register value */
tmpcr2 = TIMx->CR2;
/* Get the TIMx CCMR1 register value */
tmpccmrx = TIMx->CCMR1;
/* Reset the Output Compare Mode Bits */
tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC1M));
tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_CC1S));
/* Select the Output Compare Mode */
tmpccmrx |= TIM_OCInitStruct->TIM_OCMode;
/* Reset the Output Polarity level */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1P));
/* Set the Output Compare Polarity */
tmpccer |= TIM_OCInitStruct->TIM_OCPolarity;
/* Set the Output State */
tmpccer |= TIM_OCInitStruct->TIM_OutputState;
if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)||
(TIMx == TIM16)|| (TIMx == TIM17))
{
assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState));
assert_param(IS_TIM_OCN_POLARITY(TIM_OCInitStruct->TIM_OCNPolarity));
assert_param(IS_TIM_OCNIDLE_STATE(TIM_OCInitStruct->TIM_OCNIdleState));
assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState));
/* Reset the Output N Polarity level */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1NP));
/* Set the Output N Polarity */
tmpccer |= TIM_OCInitStruct->TIM_OCNPolarity;
/* Reset the Output N State */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC1NE));
/* Set the Output N State */
tmpccer |= TIM_OCInitStruct->TIM_OutputNState;
/* Reset the Output Compare and Output Compare N IDLE State */
tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS1));
tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS1N));
/* Set the Output Idle state */
tmpcr2 |= TIM_OCInitStruct->TIM_OCIdleState;
/* Set the Output N Idle state */
tmpcr2 |= TIM_OCInitStruct->TIM_OCNIdleState;
}
/* Write to TIMx CR2 */
TIMx->CR2 = tmpcr2;
/* Write to TIMx CCMR1 */
TIMx->CCMR1 = tmpccmrx;
/* Set the Capture Compare Register value */
TIMx->CCR1 = TIM_OCInitStruct->TIM_Pulse;
/* Write to TIMx CCER */
TIMx->CCER = tmpccer;
}
/**
* @brief Initializes the TIMx Channel2 according to the specified
* parameters in the TIM_OCInitStruct.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select
* the TIM peripheral.
* @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure
* that contains the configuration information for the specified TIM peripheral.
* @retval None
*/
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
{
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode));
assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState));
assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity));
/* Disable the Channel 2: Reset the CC2E Bit */
TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC2E));
/* Get the TIMx CCER register value */
tmpccer = TIMx->CCER;
/* Get the TIMx CR2 register value */
tmpcr2 = TIMx->CR2;
/* Get the TIMx CCMR1 register value */
tmpccmrx = TIMx->CCMR1;
/* Reset the Output Compare mode and Capture/Compare selection Bits */
tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_OC2M));
tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S));
/* Select the Output Compare Mode */
tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8);
/* Reset the Output Polarity level */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2P));
/* Set the Output Compare Polarity */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 4);
/* Set the Output State */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 4);
if((TIMx == TIM1) || (TIMx == TIM8))
{
assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState));
assert_param(IS_TIM_OCN_POLARITY(TIM_OCInitStruct->TIM_OCNPolarity));
assert_param(IS_TIM_OCNIDLE_STATE(TIM_OCInitStruct->TIM_OCNIdleState));
assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState));
/* Reset the Output N Polarity level */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2NP));
/* Set the Output N Polarity */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCNPolarity << 4);
/* Reset the Output N State */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC2NE));
/* Set the Output N State */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputNState << 4);
/* Reset the Output Compare and Output Compare N IDLE State */
tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS2));
tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS2N));
/* Set the Output Idle state */
tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 2);
/* Set the Output N Idle state */
tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCNIdleState << 2);
}
/* Write to TIMx CR2 */
TIMx->CR2 = tmpcr2;
/* Write to TIMx CCMR1 */
TIMx->CCMR1 = tmpccmrx;
/* Set the Capture Compare Register value */
TIMx->CCR2 = TIM_OCInitStruct->TIM_Pulse;
/* Write to TIMx CCER */
TIMx->CCER = tmpccer;
}
/**
* @brief Initializes the TIMx Channel3 according to the specified
* parameters in the TIM_OCInitStruct.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure
* that contains the configuration information for the specified TIM peripheral.
* @retval None
*/
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
{
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode));
assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState));
assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity));
/* Disable the Channel 2: Reset the CC2E Bit */
TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC3E));
/* Get the TIMx CCER register value */
tmpccer = TIMx->CCER;
/* Get the TIMx CR2 register value */
tmpcr2 = TIMx->CR2;
/* Get the TIMx CCMR2 register value */
tmpccmrx = TIMx->CCMR2;
/* Reset the Output Compare mode and Capture/Compare selection Bits */
tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC3M));
tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_CC3S));
/* Select the Output Compare Mode */
tmpccmrx |= TIM_OCInitStruct->TIM_OCMode;
/* Reset the Output Polarity level */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3P));
/* Set the Output Compare Polarity */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 8);
/* Set the Output State */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 8);
if((TIMx == TIM1) || (TIMx == TIM8))
{
assert_param(IS_TIM_OUTPUTN_STATE(TIM_OCInitStruct->TIM_OutputNState));
assert_param(IS_TIM_OCN_POLARITY(TIM_OCInitStruct->TIM_OCNPolarity));
assert_param(IS_TIM_OCNIDLE_STATE(TIM_OCInitStruct->TIM_OCNIdleState));
assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState));
/* Reset the Output N Polarity level */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3NP));
/* Set the Output N Polarity */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCNPolarity << 8);
/* Reset the Output N State */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC3NE));
/* Set the Output N State */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputNState << 8);
/* Reset the Output Compare and Output Compare N IDLE State */
tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS3));
tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS3N));
/* Set the Output Idle state */
tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 4);
/* Set the Output N Idle state */
tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCNIdleState << 4);
}
/* Write to TIMx CR2 */
TIMx->CR2 = tmpcr2;
/* Write to TIMx CCMR2 */
TIMx->CCMR2 = tmpccmrx;
/* Set the Capture Compare Register value */
TIMx->CCR3 = TIM_OCInitStruct->TIM_Pulse;
/* Write to TIMx CCER */
TIMx->CCER = tmpccer;
}
/**
* @brief Initializes the TIMx Channel4 according to the specified
* parameters in the TIM_OCInitStruct.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCInitStruct: pointer to a TIM_OCInitTypeDef structure
* that contains the configuration information for the specified TIM peripheral.
* @retval None
*/
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct)
{
uint16_t tmpccmrx = 0, tmpccer = 0, tmpcr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OC_MODE(TIM_OCInitStruct->TIM_OCMode));
assert_param(IS_TIM_OUTPUT_STATE(TIM_OCInitStruct->TIM_OutputState));
assert_param(IS_TIM_OC_POLARITY(TIM_OCInitStruct->TIM_OCPolarity));
/* Disable the Channel 2: Reset the CC4E Bit */
TIMx->CCER &= (uint16_t)(~((uint16_t)TIM_CCER_CC4E));
/* Get the TIMx CCER register value */
tmpccer = TIMx->CCER;
/* Get the TIMx CR2 register value */
tmpcr2 = TIMx->CR2;
/* Get the TIMx CCMR2 register value */
tmpccmrx = TIMx->CCMR2;
/* Reset the Output Compare mode and Capture/Compare selection Bits */
tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_OC4M));
tmpccmrx &= (uint16_t)(~((uint16_t)TIM_CCMR2_CC4S));
/* Select the Output Compare Mode */
tmpccmrx |= (uint16_t)(TIM_OCInitStruct->TIM_OCMode << 8);
/* Reset the Output Polarity level */
tmpccer &= (uint16_t)(~((uint16_t)TIM_CCER_CC4P));
/* Set the Output Compare Polarity */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OCPolarity << 12);
/* Set the Output State */
tmpccer |= (uint16_t)(TIM_OCInitStruct->TIM_OutputState << 12);
if((TIMx == TIM1) || (TIMx == TIM8))
{
assert_param(IS_TIM_OCIDLE_STATE(TIM_OCInitStruct->TIM_OCIdleState));
/* Reset the Output Compare IDLE State */
tmpcr2 &= (uint16_t)(~((uint16_t)TIM_CR2_OIS4));
/* Set the Output Idle state */
tmpcr2 |= (uint16_t)(TIM_OCInitStruct->TIM_OCIdleState << 6);
}
/* Write to TIMx CR2 */
TIMx->CR2 = tmpcr2;
/* Write to TIMx CCMR2 */
TIMx->CCMR2 = tmpccmrx;
/* Set the Capture Compare Register value */
TIMx->CCR4 = TIM_OCInitStruct->TIM_Pulse;
/* Write to TIMx CCER */
TIMx->CCER = tmpccer;
}
/**
* @brief Initializes the TIM peripheral according to the specified
* parameters in the TIM_ICInitStruct.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure
* that contains the configuration information for the specified TIM peripheral.
* @retval None
*/
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct)
{
/* Check the parameters */
assert_param(IS_TIM_CHANNEL(TIM_ICInitStruct->TIM_Channel));
assert_param(IS_TIM_IC_SELECTION(TIM_ICInitStruct->TIM_ICSelection));
assert_param(IS_TIM_IC_PRESCALER(TIM_ICInitStruct->TIM_ICPrescaler));
assert_param(IS_TIM_IC_FILTER(TIM_ICInitStruct->TIM_ICFilter));
if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) ||
(TIMx == TIM4) ||(TIMx == TIM5))
{
assert_param(IS_TIM_IC_POLARITY(TIM_ICInitStruct->TIM_ICPolarity));
}
else
{
assert_param(IS_TIM_IC_POLARITY_LITE(TIM_ICInitStruct->TIM_ICPolarity));
}
if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1)
{
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
/* TI1 Configuration */
TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity,
TIM_ICInitStruct->TIM_ICSelection,
TIM_ICInitStruct->TIM_ICFilter);
/* Set the Input Capture Prescaler value */
TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
}
else if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_2)
{
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
/* TI2 Configuration */
TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity,
TIM_ICInitStruct->TIM_ICSelection,
TIM_ICInitStruct->TIM_ICFilter);
/* Set the Input Capture Prescaler value */
TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
}
else if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_3)
{
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
/* TI3 Configuration */
TI3_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity,
TIM_ICInitStruct->TIM_ICSelection,
TIM_ICInitStruct->TIM_ICFilter);
/* Set the Input Capture Prescaler value */
TIM_SetIC3Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
}
else
{
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
/* TI4 Configuration */
TI4_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity,
TIM_ICInitStruct->TIM_ICSelection,
TIM_ICInitStruct->TIM_ICFilter);
/* Set the Input Capture Prescaler value */
TIM_SetIC4Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
}
}
/**
* @brief Configures the TIM peripheral according to the specified
* parameters in the TIM_ICInitStruct to measure an external PWM signal.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure
* that contains the configuration information for the specified TIM peripheral.
* @retval None
*/
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct)
{
uint16_t icoppositepolarity = TIM_ICPolarity_Rising;
uint16_t icoppositeselection = TIM_ICSelection_DirectTI;
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
/* Select the Opposite Input Polarity */
if (TIM_ICInitStruct->TIM_ICPolarity == TIM_ICPolarity_Rising)
{
icoppositepolarity = TIM_ICPolarity_Falling;
}
else
{
icoppositepolarity = TIM_ICPolarity_Rising;
}
/* Select the Opposite Input */
if (TIM_ICInitStruct->TIM_ICSelection == TIM_ICSelection_DirectTI)
{
icoppositeselection = TIM_ICSelection_IndirectTI;
}
else
{
icoppositeselection = TIM_ICSelection_DirectTI;
}
if (TIM_ICInitStruct->TIM_Channel == TIM_Channel_1)
{
/* TI1 Configuration */
TI1_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
TIM_ICInitStruct->TIM_ICFilter);
/* Set the Input Capture Prescaler value */
TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
/* TI2 Configuration */
TI2_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
/* Set the Input Capture Prescaler value */
TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
}
else
{
/* TI2 Configuration */
TI2_Config(TIMx, TIM_ICInitStruct->TIM_ICPolarity, TIM_ICInitStruct->TIM_ICSelection,
TIM_ICInitStruct->TIM_ICFilter);
/* Set the Input Capture Prescaler value */
TIM_SetIC2Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
/* TI1 Configuration */
TI1_Config(TIMx, icoppositepolarity, icoppositeselection, TIM_ICInitStruct->TIM_ICFilter);
/* Set the Input Capture Prescaler value */
TIM_SetIC1Prescaler(TIMx, TIM_ICInitStruct->TIM_ICPrescaler);
}
}
/**
* @brief Configures the: Break feature, dead time, Lock level, the OSSI,
* the OSSR State and the AOE(automatic output enable).
* @param TIMx: where x can be 1 or 8 to select the TIM
* @param TIM_BDTRInitStruct: pointer to a TIM_BDTRInitTypeDef structure that
* contains the BDTR Register configuration information for the TIM peripheral.
* @retval None
*/
void TIM_BDTRConfig(TIM_TypeDef* TIMx, TIM_BDTRInitTypeDef *TIM_BDTRInitStruct)
{
/* Check the parameters */
assert_param(IS_TIM_LIST2_PERIPH(TIMx));
assert_param(IS_TIM_OSSR_STATE(TIM_BDTRInitStruct->TIM_OSSRState));
assert_param(IS_TIM_OSSI_STATE(TIM_BDTRInitStruct->TIM_OSSIState));
assert_param(IS_TIM_LOCK_LEVEL(TIM_BDTRInitStruct->TIM_LOCKLevel));
assert_param(IS_TIM_BREAK_STATE(TIM_BDTRInitStruct->TIM_Break));
assert_param(IS_TIM_BREAK_POLARITY(TIM_BDTRInitStruct->TIM_BreakPolarity));
assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(TIM_BDTRInitStruct->TIM_AutomaticOutput));
/* Set the Lock level, the Break enable Bit and the Ploarity, the OSSR State,
the OSSI State, the dead time value and the Automatic Output Enable Bit */
TIMx->BDTR = (uint32_t)TIM_BDTRInitStruct->TIM_OSSRState | TIM_BDTRInitStruct->TIM_OSSIState |
TIM_BDTRInitStruct->TIM_LOCKLevel | TIM_BDTRInitStruct->TIM_DeadTime |
TIM_BDTRInitStruct->TIM_Break | TIM_BDTRInitStruct->TIM_BreakPolarity |
TIM_BDTRInitStruct->TIM_AutomaticOutput;
}
/**
* @brief Fills each TIM_TimeBaseInitStruct member with its default value.
* @param TIM_TimeBaseInitStruct : pointer to a TIM_TimeBaseInitTypeDef
* structure which will be initialized.
* @retval None
*/
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{
/* Set the default configuration */
TIM_TimeBaseInitStruct->TIM_Period = 0xFFFF;
TIM_TimeBaseInitStruct->TIM_Prescaler = 0x0000;
TIM_TimeBaseInitStruct->TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStruct->TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStruct->TIM_RepetitionCounter = 0x0000;
}
/**
* @brief Fills each TIM_OCInitStruct member with its default value.
* @param TIM_OCInitStruct : pointer to a TIM_OCInitTypeDef structure which will
* be initialized.
* @retval None
*/
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct)
{
/* Set the default configuration */
TIM_OCInitStruct->TIM_OCMode = TIM_OCMode_Timing;
TIM_OCInitStruct->TIM_OutputState = TIM_OutputState_Disable;
TIM_OCInitStruct->TIM_OutputNState = TIM_OutputNState_Disable;
TIM_OCInitStruct->TIM_Pulse = 0x0000;
TIM_OCInitStruct->TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct->TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStruct->TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStruct->TIM_OCNIdleState = TIM_OCNIdleState_Reset;
}
/**
* @brief Fills each TIM_ICInitStruct member with its default value.
* @param TIM_ICInitStruct: pointer to a TIM_ICInitTypeDef structure which will
* be initialized.
* @retval None
*/
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct)
{
/* Set the default configuration */
TIM_ICInitStruct->TIM_Channel = TIM_Channel_1;
TIM_ICInitStruct->TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStruct->TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStruct->TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStruct->TIM_ICFilter = 0x00;
}
/**
* @brief Fills each TIM_BDTRInitStruct member with its default value.
* @param TIM_BDTRInitStruct: pointer to a TIM_BDTRInitTypeDef structure which
* will be initialized.
* @retval None
*/
void TIM_BDTRStructInit(TIM_BDTRInitTypeDef* TIM_BDTRInitStruct)
{
/* Set the default configuration */
TIM_BDTRInitStruct->TIM_OSSRState = TIM_OSSRState_Disable;
TIM_BDTRInitStruct->TIM_OSSIState = TIM_OSSIState_Disable;
TIM_BDTRInitStruct->TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStruct->TIM_DeadTime = 0x00;
TIM_BDTRInitStruct->TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStruct->TIM_BreakPolarity = TIM_BreakPolarity_Low;
TIM_BDTRInitStruct->TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;
}
/**
* @brief Enables or disables the specified TIM peripheral.
* @param TIMx: where x can be 1 to 17 to select the TIMx peripheral.
* @param NewState: new state of the TIMx peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the TIM Counter */
TIMx->CR1 |= TIM_CR1_CEN;
}
else
{
/* Disable the TIM Counter */
TIMx->CR1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN));
}
}
/**
* @brief Enables or disables the TIM peripheral Main Outputs.
* @param TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIMx peripheral.
* @param NewState: new state of the TIM peripheral Main Outputs.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_LIST2_PERIPH(TIMx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the TIM Main Output */
TIMx->BDTR |= TIM_BDTR_MOE;
}
else
{
/* Disable the TIM Main Output */
TIMx->BDTR &= (uint16_t)(~((uint16_t)TIM_BDTR_MOE));
}
}
/**
* @brief Enables or disables the specified TIM interrupts.
* @param TIMx: where x can be 1 to 17 to select the TIMx peripheral.
* @param TIM_IT: specifies the TIM interrupts sources to be enabled or disabled.
* This parameter can be any combination of the following values:
* @arg TIM_IT_Update: TIM update Interrupt source
* @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
* @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
* @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
* @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
* @arg TIM_IT_COM: TIM Commutation Interrupt source
* @arg TIM_IT_Trigger: TIM Trigger Interrupt source
* @arg TIM_IT_Break: TIM Break Interrupt source
* @note
* - TIM6 and TIM7 can only generate an update interrupt.
* - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,
* TIM_IT_CC2 or TIM_IT_Trigger.
* - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.
* - TIM_IT_Break is used only with TIM1, TIM8 and TIM15.
* - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.
* @param NewState: new state of the TIM interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_IT(TIM_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the Interrupt sources */
TIMx->DIER |= TIM_IT;
}
else
{
/* Disable the Interrupt sources */
TIMx->DIER &= (uint16_t)~TIM_IT;
}
}
/**
* @brief Configures the TIMx event to be generate by software.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param TIM_EventSource: specifies the event source.
* This parameter can be one or more of the following values:
* @arg TIM_EventSource_Update: Timer update Event source
* @arg TIM_EventSource_CC1: Timer Capture Compare 1 Event source
* @arg TIM_EventSource_CC2: Timer Capture Compare 2 Event source
* @arg TIM_EventSource_CC3: Timer Capture Compare 3 Event source
* @arg TIM_EventSource_CC4: Timer Capture Compare 4 Event source
* @arg TIM_EventSource_COM: Timer COM event source
* @arg TIM_EventSource_Trigger: Timer Trigger Event source
* @arg TIM_EventSource_Break: Timer Break event source
* @note
* - TIM6 and TIM7 can only generate an update event.
* - TIM_EventSource_COM and TIM_EventSource_Break are used only with TIM1 and TIM8.
* @retval None
*/
void TIM_GenerateEvent(TIM_TypeDef* TIMx, uint16_t TIM_EventSource)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_EVENT_SOURCE(TIM_EventSource));
/* Set the event sources */
TIMx->EGR = TIM_EventSource;
}
/**
* @brief Configures the TIMx's DMA interface.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 15, 16 or 17 to select
* the TIM peripheral.
* @param TIM_DMABase: DMA Base address.
* This parameter can be one of the following values:
* @arg TIM_DMABase_CR, TIM_DMABase_CR2, TIM_DMABase_SMCR,
* TIM_DMABase_DIER, TIM1_DMABase_SR, TIM_DMABase_EGR,
* TIM_DMABase_CCMR1, TIM_DMABase_CCMR2, TIM_DMABase_CCER,
* TIM_DMABase_CNT, TIM_DMABase_PSC, TIM_DMABase_ARR,
* TIM_DMABase_RCR, TIM_DMABase_CCR1, TIM_DMABase_CCR2,
* TIM_DMABase_CCR3, TIM_DMABase_CCR4, TIM_DMABase_BDTR,
* TIM_DMABase_DCR.
* @param TIM_DMABurstLength: DMA Burst length.
* This parameter can be one value between:
* TIM_DMABurstLength_1Transfer and TIM_DMABurstLength_18Transfers.
* @retval None
*/
void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength)
{
/* Check the parameters */
assert_param(IS_TIM_LIST4_PERIPH(TIMx));
assert_param(IS_TIM_DMA_BASE(TIM_DMABase));
assert_param(IS_TIM_DMA_LENGTH(TIM_DMABurstLength));
/* Set the DMA Base and the DMA Burst Length */
TIMx->DCR = TIM_DMABase | TIM_DMABurstLength;
}
/**
* @brief Enables or disables the TIMx's DMA Requests.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 6, 7, 8, 15, 16 or 17
* to select the TIM peripheral.
* @param TIM_DMASource: specifies the DMA Request sources.
* This parameter can be any combination of the following values:
* @arg TIM_DMA_Update: TIM update Interrupt source
* @arg TIM_DMA_CC1: TIM Capture Compare 1 DMA source
* @arg TIM_DMA_CC2: TIM Capture Compare 2 DMA source
* @arg TIM_DMA_CC3: TIM Capture Compare 3 DMA source
* @arg TIM_DMA_CC4: TIM Capture Compare 4 DMA source
* @arg TIM_DMA_COM: TIM Commutation DMA source
* @arg TIM_DMA_Trigger: TIM Trigger DMA source
* @param NewState: new state of the DMA Request sources.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_LIST9_PERIPH(TIMx));
assert_param(IS_TIM_DMA_SOURCE(TIM_DMASource));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the DMA sources */
TIMx->DIER |= TIM_DMASource;
}
else
{
/* Disable the DMA sources */
TIMx->DIER &= (uint16_t)~TIM_DMASource;
}
}
/**
* @brief Configures the TIMx internal Clock
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15
* to select the TIM peripheral.
* @retval None
*/
void TIM_InternalClockConfig(TIM_TypeDef* TIMx)
{
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
/* Disable slave mode to clock the prescaler directly with the internal clock */
TIMx->SMCR &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
}
/**
* @brief Configures the TIMx Internal Trigger as External Clock
* @param TIMx: where x can be 1, 2, 3, 4, 5, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_ITRSource: Trigger source.
* This parameter can be one of the following values:
* @param TIM_TS_ITR0: Internal Trigger 0
* @param TIM_TS_ITR1: Internal Trigger 1
* @param TIM_TS_ITR2: Internal Trigger 2
* @param TIM_TS_ITR3: Internal Trigger 3
* @retval None
*/
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource)
{
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_INTERNAL_TRIGGER_SELECTION(TIM_InputTriggerSource));
/* Select the Internal Trigger */
TIM_SelectInputTrigger(TIMx, TIM_InputTriggerSource);
/* Select the External clock mode1 */
TIMx->SMCR |= TIM_SlaveMode_External1;
}
/**
* @brief Configures the TIMx Trigger as External Clock
* @param TIMx: where x can be 1, 2, 3, 4, 5, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_TIxExternalCLKSource: Trigger source.
* This parameter can be one of the following values:
* @arg TIM_TIxExternalCLK1Source_TI1ED: TI1 Edge Detector
* @arg TIM_TIxExternalCLK1Source_TI1: Filtered Timer Input 1
* @arg TIM_TIxExternalCLK1Source_TI2: Filtered Timer Input 2
* @param TIM_ICPolarity: specifies the TIx Polarity.
* This parameter can be one of the following values:
* @arg TIM_ICPolarity_Rising
* @arg TIM_ICPolarity_Falling
* @param ICFilter : specifies the filter value.
* This parameter must be a value between 0x0 and 0xF.
* @retval None
*/
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
uint16_t TIM_ICPolarity, uint16_t ICFilter)
{
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_TIXCLK_SOURCE(TIM_TIxExternalCLKSource));
assert_param(IS_TIM_IC_POLARITY(TIM_ICPolarity));
assert_param(IS_TIM_IC_FILTER(ICFilter));
/* Configure the Timer Input Clock Source */
if (TIM_TIxExternalCLKSource == TIM_TIxExternalCLK1Source_TI2)
{
TI2_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter);
}
else
{
TI1_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter);
}
/* Select the Trigger source */
TIM_SelectInputTrigger(TIMx, TIM_TIxExternalCLKSource);
/* Select the External clock mode1 */
TIMx->SMCR |= TIM_SlaveMode_External1;
}
/**
* @brief Configures the External clock Mode1
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_ExtTRGPrescaler: The external Trigger Prescaler.
* This parameter can be one of the following values:
* @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.
* @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.
* @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.
* @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.
* @param TIM_ExtTRGPolarity: The external Trigger Polarity.
* This parameter can be one of the following values:
* @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.
* @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.
* @param ExtTRGFilter: External Trigger Filter.
* This parameter must be a value between 0x00 and 0x0F
* @retval None
*/
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
uint16_t ExtTRGFilter)
{
uint16_t tmpsmcr = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));
assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));
assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));
/* Configure the ETR Clock source */
TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter);
/* Get the TIMx SMCR register value */
tmpsmcr = TIMx->SMCR;
/* Reset the SMS Bits */
tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
/* Select the External clock mode1 */
tmpsmcr |= TIM_SlaveMode_External1;
/* Select the Trigger selection : ETRF */
tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS));
tmpsmcr |= TIM_TS_ETRF;
/* Write to TIMx SMCR */
TIMx->SMCR = tmpsmcr;
}
/**
* @brief Configures the External clock Mode2
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_ExtTRGPrescaler: The external Trigger Prescaler.
* This parameter can be one of the following values:
* @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.
* @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.
* @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.
* @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.
* @param TIM_ExtTRGPolarity: The external Trigger Polarity.
* This parameter can be one of the following values:
* @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.
* @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.
* @param ExtTRGFilter: External Trigger Filter.
* This parameter must be a value between 0x00 and 0x0F
* @retval None
*/
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter)
{
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));
assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));
assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));
/* Configure the ETR Clock source */
TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter);
/* Enable the External clock mode2 */
TIMx->SMCR |= TIM_SMCR_ECE;
}
/**
* @brief Configures the TIMx External Trigger (ETR).
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_ExtTRGPrescaler: The external Trigger Prescaler.
* This parameter can be one of the following values:
* @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.
* @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.
* @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.
* @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.
* @param TIM_ExtTRGPolarity: The external Trigger Polarity.
* This parameter can be one of the following values:
* @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.
* @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.
* @param ExtTRGFilter: External Trigger Filter.
* This parameter must be a value between 0x00 and 0x0F
* @retval None
*/
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
uint16_t ExtTRGFilter)
{
uint16_t tmpsmcr = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));
assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));
assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));
tmpsmcr = TIMx->SMCR;
/* Reset the ETR Bits */
tmpsmcr &= SMCR_ETR_Mask;
/* Set the Prescaler, the Filter value and the Polarity */
tmpsmcr |= (uint16_t)(TIM_ExtTRGPrescaler | (uint16_t)(TIM_ExtTRGPolarity | (uint16_t)(ExtTRGFilter << (uint16_t)8)));
/* Write to TIMx SMCR */
TIMx->SMCR = tmpsmcr;
}
/**
* @brief Configures the TIMx Prescaler.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param Prescaler: specifies the Prescaler Register value
* @param TIM_PSCReloadMode: specifies the TIM Prescaler Reload mode
* This parameter can be one of the following values:
* @arg TIM_PSCReloadMode_Update: The Prescaler is loaded at the update event.
* @arg TIM_PSCReloadMode_Immediate: The Prescaler is loaded immediately.
* @retval None
*/
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_PRESCALER_RELOAD(TIM_PSCReloadMode));
/* Set the Prescaler value */
TIMx->PSC = Prescaler;
/* Set or reset the UG Bit */
TIMx->EGR = TIM_PSCReloadMode;
}
/**
* @brief Specifies the TIMx Counter Mode to be used.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_CounterMode: specifies the Counter Mode to be used
* This parameter can be one of the following values:
* @arg TIM_CounterMode_Up: TIM Up Counting Mode
* @arg TIM_CounterMode_Down: TIM Down Counting Mode
* @arg TIM_CounterMode_CenterAligned1: TIM Center Aligned Mode1
* @arg TIM_CounterMode_CenterAligned2: TIM Center Aligned Mode2
* @arg TIM_CounterMode_CenterAligned3: TIM Center Aligned Mode3
* @retval None
*/
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode)
{
uint16_t tmpcr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_COUNTER_MODE(TIM_CounterMode));
tmpcr1 = TIMx->CR1;
/* Reset the CMS and DIR Bits */
tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
/* Set the Counter Mode */
tmpcr1 |= TIM_CounterMode;
/* Write to TIMx CR1 register */
TIMx->CR1 = tmpcr1;
}
/**
* @brief Selects the Input Trigger source
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_InputTriggerSource: The Input Trigger source.
* This parameter can be one of the following values:
* @arg TIM_TS_ITR0: Internal Trigger 0
* @arg TIM_TS_ITR1: Internal Trigger 1
* @arg TIM_TS_ITR2: Internal Trigger 2
* @arg TIM_TS_ITR3: Internal Trigger 3
* @arg TIM_TS_TI1F_ED: TI1 Edge Detector
* @arg TIM_TS_TI1FP1: Filtered Timer Input 1
* @arg TIM_TS_TI2FP2: Filtered Timer Input 2
* @arg TIM_TS_ETRF: External Trigger input
* @retval None
*/
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource)
{
uint16_t tmpsmcr = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_TRIGGER_SELECTION(TIM_InputTriggerSource));
/* Get the TIMx SMCR register value */
tmpsmcr = TIMx->SMCR;
/* Reset the TS Bits */
tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS));
/* Set the Input Trigger source */
tmpsmcr |= TIM_InputTriggerSource;
/* Write to TIMx SMCR */
TIMx->SMCR = tmpsmcr;
}
/**
* @brief Configures the TIMx Encoder Interface.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_EncoderMode: specifies the TIMx Encoder Mode.
* This parameter can be one of the following values:
* @arg TIM_EncoderMode_TI1: Counter counts on TI1FP1 edge depending on TI2FP2 level.
* @arg TIM_EncoderMode_TI2: Counter counts on TI2FP2 edge depending on TI1FP1 level.
* @arg TIM_EncoderMode_TI12: Counter counts on both TI1FP1 and TI2FP2 edges depending
* on the level of the other input.
* @param TIM_IC1Polarity: specifies the IC1 Polarity
* This parameter can be one of the following values:
* @arg TIM_ICPolarity_Falling: IC Falling edge.
* @arg TIM_ICPolarity_Rising: IC Rising edge.
* @param TIM_IC2Polarity: specifies the IC2 Polarity
* This parameter can be one of the following values:
* @arg TIM_ICPolarity_Falling: IC Falling edge.
* @arg TIM_ICPolarity_Rising: IC Rising edge.
* @retval None
*/
void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,
uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity)
{
uint16_t tmpsmcr = 0;
uint16_t tmpccmr1 = 0;
uint16_t tmpccer = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST5_PERIPH(TIMx));
assert_param(IS_TIM_ENCODER_MODE(TIM_EncoderMode));
assert_param(IS_TIM_IC_POLARITY(TIM_IC1Polarity));
assert_param(IS_TIM_IC_POLARITY(TIM_IC2Polarity));
/* Get the TIMx SMCR register value */
tmpsmcr = TIMx->SMCR;
/* Get the TIMx CCMR1 register value */
tmpccmr1 = TIMx->CCMR1;
/* Get the TIMx CCER register value */
tmpccer = TIMx->CCER;
/* Set the encoder Mode */
tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
tmpsmcr |= TIM_EncoderMode;
/* Select the Capture Compare 1 and the Capture Compare 2 as input */
tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & (uint16_t)(~((uint16_t)TIM_CCMR1_CC2S)));
tmpccmr1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
/* Set the TI1 and the TI2 Polarities */
tmpccer &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCER_CC1P)) & ((uint16_t)~((uint16_t)TIM_CCER_CC2P)));
tmpccer |= (uint16_t)(TIM_IC1Polarity | (uint16_t)(TIM_IC2Polarity << (uint16_t)4));
/* Write to TIMx SMCR */
TIMx->SMCR = tmpsmcr;
/* Write to TIMx CCMR1 */
TIMx->CCMR1 = tmpccmr1;
/* Write to TIMx CCER */
TIMx->CCER = tmpccer;
}
/**
* @brief Forces the TIMx output 1 waveform to active or inactive level.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform.
* This parameter can be one of the following values:
* @arg TIM_ForcedAction_Active: Force active level on OC1REF
* @arg TIM_ForcedAction_InActive: Force inactive level on OC1REF.
* @retval None
*/
void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
{
uint16_t tmpccmr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction));
tmpccmr1 = TIMx->CCMR1;
/* Reset the OC1M Bits */
tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1M);
/* Configure The Forced output Mode */
tmpccmr1 |= TIM_ForcedAction;
/* Write to TIMx CCMR1 register */
TIMx->CCMR1 = tmpccmr1;
}
/**
* @brief Forces the TIMx output 2 waveform to active or inactive level.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform.
* This parameter can be one of the following values:
* @arg TIM_ForcedAction_Active: Force active level on OC2REF
* @arg TIM_ForcedAction_InActive: Force inactive level on OC2REF.
* @retval None
*/
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
{
uint16_t tmpccmr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction));
tmpccmr1 = TIMx->CCMR1;
/* Reset the OC2M Bits */
tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2M);
/* Configure The Forced output Mode */
tmpccmr1 |= (uint16_t)(TIM_ForcedAction << 8);
/* Write to TIMx CCMR1 register */
TIMx->CCMR1 = tmpccmr1;
}
/**
* @brief Forces the TIMx output 3 waveform to active or inactive level.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform.
* This parameter can be one of the following values:
* @arg TIM_ForcedAction_Active: Force active level on OC3REF
* @arg TIM_ForcedAction_InActive: Force inactive level on OC3REF.
* @retval None
*/
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
{
uint16_t tmpccmr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction));
tmpccmr2 = TIMx->CCMR2;
/* Reset the OC1M Bits */
tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3M);
/* Configure The Forced output Mode */
tmpccmr2 |= TIM_ForcedAction;
/* Write to TIMx CCMR2 register */
TIMx->CCMR2 = tmpccmr2;
}
/**
* @brief Forces the TIMx output 4 waveform to active or inactive level.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_ForcedAction: specifies the forced Action to be set to the output waveform.
* This parameter can be one of the following values:
* @arg TIM_ForcedAction_Active: Force active level on OC4REF
* @arg TIM_ForcedAction_InActive: Force inactive level on OC4REF.
* @retval None
*/
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction)
{
uint16_t tmpccmr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_FORCED_ACTION(TIM_ForcedAction));
tmpccmr2 = TIMx->CCMR2;
/* Reset the OC2M Bits */
tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4M);
/* Configure The Forced output Mode */
tmpccmr2 |= (uint16_t)(TIM_ForcedAction << 8);
/* Write to TIMx CCMR2 register */
TIMx->CCMR2 = tmpccmr2;
}
/**
* @brief Enables or disables TIMx peripheral Preload register on ARR.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param NewState: new state of the TIMx peripheral Preload register
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Set the ARR Preload Bit */
TIMx->CR1 |= TIM_CR1_ARPE;
}
else
{
/* Reset the ARR Preload Bit */
TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_ARPE);
}
}
/**
* @brief Selects the TIM peripheral Commutation event.
* @param TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIMx peripheral
* @param NewState: new state of the Commutation event.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_SelectCOM(TIM_TypeDef* TIMx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_LIST2_PERIPH(TIMx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Set the COM Bit */
TIMx->CR2 |= TIM_CR2_CCUS;
}
else
{
/* Reset the COM Bit */
TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_CCUS);
}
}
/**
* @brief Selects the TIMx peripheral Capture Compare DMA source.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 15, 16 or 17 to select
* the TIM peripheral.
* @param NewState: new state of the Capture Compare DMA source
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_SelectCCDMA(TIM_TypeDef* TIMx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_LIST4_PERIPH(TIMx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Set the CCDS Bit */
TIMx->CR2 |= TIM_CR2_CCDS;
}
else
{
/* Reset the CCDS Bit */
TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_CCDS);
}
}
/**
* @brief Sets or Resets the TIM peripheral Capture Compare Preload Control bit.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8 or 15
* to select the TIMx peripheral
* @param NewState: new state of the Capture Compare Preload Control bit
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_CCPreloadControl(TIM_TypeDef* TIMx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_LIST5_PERIPH(TIMx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Set the CCPC Bit */
TIMx->CR2 |= TIM_CR2_CCPC;
}
else
{
/* Reset the CCPC Bit */
TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_CCPC);
}
}
/**
* @brief Enables or disables the TIMx peripheral Preload register on CCR1.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_OCPreload: new state of the TIMx peripheral Preload register
* This parameter can be one of the following values:
* @arg TIM_OCPreload_Enable
* @arg TIM_OCPreload_Disable
* @retval None
*/
void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
{
uint16_t tmpccmr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload));
tmpccmr1 = TIMx->CCMR1;
/* Reset the OC1PE Bit */
tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1PE);
/* Enable or Disable the Output Compare Preload feature */
tmpccmr1 |= TIM_OCPreload;
/* Write to TIMx CCMR1 register */
TIMx->CCMR1 = tmpccmr1;
}
/**
* @brief Enables or disables the TIMx peripheral Preload register on CCR2.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select
* the TIM peripheral.
* @param TIM_OCPreload: new state of the TIMx peripheral Preload register
* This parameter can be one of the following values:
* @arg TIM_OCPreload_Enable
* @arg TIM_OCPreload_Disable
* @retval None
*/
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
{
uint16_t tmpccmr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload));
tmpccmr1 = TIMx->CCMR1;
/* Reset the OC2PE Bit */
tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2PE);
/* Enable or Disable the Output Compare Preload feature */
tmpccmr1 |= (uint16_t)(TIM_OCPreload << 8);
/* Write to TIMx CCMR1 register */
TIMx->CCMR1 = tmpccmr1;
}
/**
* @brief Enables or disables the TIMx peripheral Preload register on CCR3.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCPreload: new state of the TIMx peripheral Preload register
* This parameter can be one of the following values:
* @arg TIM_OCPreload_Enable
* @arg TIM_OCPreload_Disable
* @retval None
*/
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
{
uint16_t tmpccmr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload));
tmpccmr2 = TIMx->CCMR2;
/* Reset the OC3PE Bit */
tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3PE);
/* Enable or Disable the Output Compare Preload feature */
tmpccmr2 |= TIM_OCPreload;
/* Write to TIMx CCMR2 register */
TIMx->CCMR2 = tmpccmr2;
}
/**
* @brief Enables or disables the TIMx peripheral Preload register on CCR4.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCPreload: new state of the TIMx peripheral Preload register
* This parameter can be one of the following values:
* @arg TIM_OCPreload_Enable
* @arg TIM_OCPreload_Disable
* @retval None
*/
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload)
{
uint16_t tmpccmr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OCPRELOAD_STATE(TIM_OCPreload));
tmpccmr2 = TIMx->CCMR2;
/* Reset the OC4PE Bit */
tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4PE);
/* Enable or Disable the Output Compare Preload feature */
tmpccmr2 |= (uint16_t)(TIM_OCPreload << 8);
/* Write to TIMx CCMR2 register */
TIMx->CCMR2 = tmpccmr2;
}
/**
* @brief Configures the TIMx Output Compare 1 Fast feature.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_OCFast: new state of the Output Compare Fast Enable Bit.
* This parameter can be one of the following values:
* @arg TIM_OCFast_Enable: TIM output compare fast enable
* @arg TIM_OCFast_Disable: TIM output compare fast disable
* @retval None
*/
void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
{
uint16_t tmpccmr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast));
/* Get the TIMx CCMR1 register value */
tmpccmr1 = TIMx->CCMR1;
/* Reset the OC1FE Bit */
tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1FE);
/* Enable or Disable the Output Compare Fast Bit */
tmpccmr1 |= TIM_OCFast;
/* Write to TIMx CCMR1 */
TIMx->CCMR1 = tmpccmr1;
}
/**
* @brief Configures the TIMx Output Compare 2 Fast feature.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select
* the TIM peripheral.
* @param TIM_OCFast: new state of the Output Compare Fast Enable Bit.
* This parameter can be one of the following values:
* @arg TIM_OCFast_Enable: TIM output compare fast enable
* @arg TIM_OCFast_Disable: TIM output compare fast disable
* @retval None
*/
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
{
uint16_t tmpccmr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast));
/* Get the TIMx CCMR1 register value */
tmpccmr1 = TIMx->CCMR1;
/* Reset the OC2FE Bit */
tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2FE);
/* Enable or Disable the Output Compare Fast Bit */
tmpccmr1 |= (uint16_t)(TIM_OCFast << 8);
/* Write to TIMx CCMR1 */
TIMx->CCMR1 = tmpccmr1;
}
/**
* @brief Configures the TIMx Output Compare 3 Fast feature.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCFast: new state of the Output Compare Fast Enable Bit.
* This parameter can be one of the following values:
* @arg TIM_OCFast_Enable: TIM output compare fast enable
* @arg TIM_OCFast_Disable: TIM output compare fast disable
* @retval None
*/
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
{
uint16_t tmpccmr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast));
/* Get the TIMx CCMR2 register value */
tmpccmr2 = TIMx->CCMR2;
/* Reset the OC3FE Bit */
tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3FE);
/* Enable or Disable the Output Compare Fast Bit */
tmpccmr2 |= TIM_OCFast;
/* Write to TIMx CCMR2 */
TIMx->CCMR2 = tmpccmr2;
}
/**
* @brief Configures the TIMx Output Compare 4 Fast feature.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCFast: new state of the Output Compare Fast Enable Bit.
* This parameter can be one of the following values:
* @arg TIM_OCFast_Enable: TIM output compare fast enable
* @arg TIM_OCFast_Disable: TIM output compare fast disable
* @retval None
*/
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast)
{
uint16_t tmpccmr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OCFAST_STATE(TIM_OCFast));
/* Get the TIMx CCMR2 register value */
tmpccmr2 = TIMx->CCMR2;
/* Reset the OC4FE Bit */
tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4FE);
/* Enable or Disable the Output Compare Fast Bit */
tmpccmr2 |= (uint16_t)(TIM_OCFast << 8);
/* Write to TIMx CCMR2 */
TIMx->CCMR2 = tmpccmr2;
}
/**
* @brief Clears or safeguards the OCREF1 signal on an external event
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCClear: new state of the Output Compare Clear Enable Bit.
* This parameter can be one of the following values:
* @arg TIM_OCClear_Enable: TIM Output clear enable
* @arg TIM_OCClear_Disable: TIM Output clear disable
* @retval None
*/
void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
{
uint16_t tmpccmr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear));
tmpccmr1 = TIMx->CCMR1;
/* Reset the OC1CE Bit */
tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC1CE);
/* Enable or Disable the Output Compare Clear Bit */
tmpccmr1 |= TIM_OCClear;
/* Write to TIMx CCMR1 register */
TIMx->CCMR1 = tmpccmr1;
}
/**
* @brief Clears or safeguards the OCREF2 signal on an external event
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCClear: new state of the Output Compare Clear Enable Bit.
* This parameter can be one of the following values:
* @arg TIM_OCClear_Enable: TIM Output clear enable
* @arg TIM_OCClear_Disable: TIM Output clear disable
* @retval None
*/
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
{
uint16_t tmpccmr1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear));
tmpccmr1 = TIMx->CCMR1;
/* Reset the OC2CE Bit */
tmpccmr1 &= (uint16_t)~((uint16_t)TIM_CCMR1_OC2CE);
/* Enable or Disable the Output Compare Clear Bit */
tmpccmr1 |= (uint16_t)(TIM_OCClear << 8);
/* Write to TIMx CCMR1 register */
TIMx->CCMR1 = tmpccmr1;
}
/**
* @brief Clears or safeguards the OCREF3 signal on an external event
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCClear: new state of the Output Compare Clear Enable Bit.
* This parameter can be one of the following values:
* @arg TIM_OCClear_Enable: TIM Output clear enable
* @arg TIM_OCClear_Disable: TIM Output clear disable
* @retval None
*/
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
{
uint16_t tmpccmr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear));
tmpccmr2 = TIMx->CCMR2;
/* Reset the OC3CE Bit */
tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC3CE);
/* Enable or Disable the Output Compare Clear Bit */
tmpccmr2 |= TIM_OCClear;
/* Write to TIMx CCMR2 register */
TIMx->CCMR2 = tmpccmr2;
}
/**
* @brief Clears or safeguards the OCREF4 signal on an external event
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCClear: new state of the Output Compare Clear Enable Bit.
* This parameter can be one of the following values:
* @arg TIM_OCClear_Enable: TIM Output clear enable
* @arg TIM_OCClear_Disable: TIM Output clear disable
* @retval None
*/
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear)
{
uint16_t tmpccmr2 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OCCLEAR_STATE(TIM_OCClear));
tmpccmr2 = TIMx->CCMR2;
/* Reset the OC4CE Bit */
tmpccmr2 &= (uint16_t)~((uint16_t)TIM_CCMR2_OC4CE);
/* Enable or Disable the Output Compare Clear Bit */
tmpccmr2 |= (uint16_t)(TIM_OCClear << 8);
/* Write to TIMx CCMR2 register */
TIMx->CCMR2 = tmpccmr2;
}
/**
* @brief Configures the TIMx channel 1 polarity.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_OCPolarity: specifies the OC1 Polarity
* This parameter can be one of the following values:
* @arg TIM_OCPolarity_High: Output Compare active high
* @arg TIM_OCPolarity_Low: Output Compare active low
* @retval None
*/
void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
{
uint16_t tmpccer = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity));
tmpccer = TIMx->CCER;
/* Set or Reset the CC1P Bit */
tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1P);
tmpccer |= TIM_OCPolarity;
/* Write to TIMx CCER register */
TIMx->CCER = tmpccer;
}
/**
* @brief Configures the TIMx Channel 1N polarity.
* @param TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIM peripheral.
* @param TIM_OCNPolarity: specifies the OC1N Polarity
* This parameter can be one of the following values:
* @arg TIM_OCNPolarity_High: Output Compare active high
* @arg TIM_OCNPolarity_Low: Output Compare active low
* @retval None
*/
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity)
{
uint16_t tmpccer = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST2_PERIPH(TIMx));
assert_param(IS_TIM_OCN_POLARITY(TIM_OCNPolarity));
tmpccer = TIMx->CCER;
/* Set or Reset the CC1NP Bit */
tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC1NP);
tmpccer |= TIM_OCNPolarity;
/* Write to TIMx CCER register */
TIMx->CCER = tmpccer;
}
/**
* @brief Configures the TIMx channel 2 polarity.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_OCPolarity: specifies the OC2 Polarity
* This parameter can be one of the following values:
* @arg TIM_OCPolarity_High: Output Compare active high
* @arg TIM_OCPolarity_Low: Output Compare active low
* @retval None
*/
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
{
uint16_t tmpccer = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity));
tmpccer = TIMx->CCER;
/* Set or Reset the CC2P Bit */
tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2P);
tmpccer |= (uint16_t)(TIM_OCPolarity << 4);
/* Write to TIMx CCER register */
TIMx->CCER = tmpccer;
}
/**
* @brief Configures the TIMx Channel 2N polarity.
* @param TIMx: where x can be 1 or 8 to select the TIM peripheral.
* @param TIM_OCNPolarity: specifies the OC2N Polarity
* This parameter can be one of the following values:
* @arg TIM_OCNPolarity_High: Output Compare active high
* @arg TIM_OCNPolarity_Low: Output Compare active low
* @retval None
*/
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity)
{
uint16_t tmpccer = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST1_PERIPH(TIMx));
assert_param(IS_TIM_OCN_POLARITY(TIM_OCNPolarity));
tmpccer = TIMx->CCER;
/* Set or Reset the CC2NP Bit */
tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC2NP);
tmpccer |= (uint16_t)(TIM_OCNPolarity << 4);
/* Write to TIMx CCER register */
TIMx->CCER = tmpccer;
}
/**
* @brief Configures the TIMx channel 3 polarity.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCPolarity: specifies the OC3 Polarity
* This parameter can be one of the following values:
* @arg TIM_OCPolarity_High: Output Compare active high
* @arg TIM_OCPolarity_Low: Output Compare active low
* @retval None
*/
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
{
uint16_t tmpccer = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity));
tmpccer = TIMx->CCER;
/* Set or Reset the CC3P Bit */
tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3P);
tmpccer |= (uint16_t)(TIM_OCPolarity << 8);
/* Write to TIMx CCER register */
TIMx->CCER = tmpccer;
}
/**
* @brief Configures the TIMx Channel 3N polarity.
* @param TIMx: where x can be 1 or 8 to select the TIM peripheral.
* @param TIM_OCNPolarity: specifies the OC3N Polarity
* This parameter can be one of the following values:
* @arg TIM_OCNPolarity_High: Output Compare active high
* @arg TIM_OCNPolarity_Low: Output Compare active low
* @retval None
*/
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity)
{
uint16_t tmpccer = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST1_PERIPH(TIMx));
assert_param(IS_TIM_OCN_POLARITY(TIM_OCNPolarity));
tmpccer = TIMx->CCER;
/* Set or Reset the CC3NP Bit */
tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC3NP);
tmpccer |= (uint16_t)(TIM_OCNPolarity << 8);
/* Write to TIMx CCER register */
TIMx->CCER = tmpccer;
}
/**
* @brief Configures the TIMx channel 4 polarity.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_OCPolarity: specifies the OC4 Polarity
* This parameter can be one of the following values:
* @arg TIM_OCPolarity_High: Output Compare active high
* @arg TIM_OCPolarity_Low: Output Compare active low
* @retval None
*/
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity)
{
uint16_t tmpccer = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_OC_POLARITY(TIM_OCPolarity));
tmpccer = TIMx->CCER;
/* Set or Reset the CC4P Bit */
tmpccer &= (uint16_t)~((uint16_t)TIM_CCER_CC4P);
tmpccer |= (uint16_t)(TIM_OCPolarity << 12);
/* Write to TIMx CCER register */
TIMx->CCER = tmpccer;
}
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/**
* @brief Enables or disables the TIM Capture Compare Channel x.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_Channel: specifies the TIM Channel
* This parameter can be one of the following values:
* @arg TIM_Channel_1: TIM Channel 1
* @arg TIM_Channel_2: TIM Channel 2
* @arg TIM_Channel_3: TIM Channel 3
* @arg TIM_Channel_4: TIM Channel 4
* @param TIM_CCx: specifies the TIM Channel CCxE bit new state.
* This parameter can be: TIM_CCx_Enable or TIM_CCx_Disable.
* @retval None
*/
void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx)
{
uint16_t tmp = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_CHANNEL(TIM_Channel));
assert_param(IS_TIM_CCX(TIM_CCx));
tmp = CCER_CCE_Set << TIM_Channel;
/* Reset the CCxE Bit */
TIMx->CCER &= (uint16_t)~ tmp;
/* Set or reset the CCxE Bit */
TIMx->CCER |= (uint16_t)(TIM_CCx << TIM_Channel);
}
/**
* @brief Enables or disables the TIM Capture Compare Channel xN.
* @param TIMx: where x can be 1, 8, 15, 16 or 17 to select the TIM peripheral.
* @param TIM_Channel: specifies the TIM Channel
* This parameter can be one of the following values:
* @arg TIM_Channel_1: TIM Channel 1
* @arg TIM_Channel_2: TIM Channel 2
* @arg TIM_Channel_3: TIM Channel 3
* @param TIM_CCxN: specifies the TIM Channel CCxNE bit new state.
* This parameter can be: TIM_CCxN_Enable or TIM_CCxN_Disable.
* @retval None
*/
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN)
{
uint16_t tmp = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST2_PERIPH(TIMx));
assert_param(IS_TIM_COMPLEMENTARY_CHANNEL(TIM_Channel));
assert_param(IS_TIM_CCXN(TIM_CCxN));
tmp = CCER_CCNE_Set << TIM_Channel;
/* Reset the CCxNE Bit */
TIMx->CCER &= (uint16_t) ~tmp;
/* Set or reset the CCxNE Bit */
TIMx->CCER |= (uint16_t)(TIM_CCxN << TIM_Channel);
}
/**
* @brief Selects the TIM Output Compare Mode.
* @note This function disables the selected channel before changing the Output
* Compare Mode.
* User has to enable this channel using TIM_CCxCmd and TIM_CCxNCmd functions.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_Channel: specifies the TIM Channel
* This parameter can be one of the following values:
* @arg TIM_Channel_1: TIM Channel 1
* @arg TIM_Channel_2: TIM Channel 2
* @arg TIM_Channel_3: TIM Channel 3
* @arg TIM_Channel_4: TIM Channel 4
* @param TIM_OCMode: specifies the TIM Output Compare Mode.
* This parameter can be one of the following values:
* @arg TIM_OCMode_Timing
* @arg TIM_OCMode_Active
* @arg TIM_OCMode_Toggle
* @arg TIM_OCMode_PWM1
* @arg TIM_OCMode_PWM2
* @arg TIM_ForcedAction_Active
* @arg TIM_ForcedAction_InActive
* @retval None
*/
void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode)
{
uint32_t tmp = 0;
uint16_t tmp1 = 0;
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_CHANNEL(TIM_Channel));
assert_param(IS_TIM_OCM(TIM_OCMode));
tmp = (uint32_t) TIMx;
tmp += CCMR_Offset;
tmp1 = CCER_CCE_Set << (uint16_t)TIM_Channel;
/* Disable the Channel: Reset the CCxE Bit */
TIMx->CCER &= (uint16_t) ~tmp1;
if((TIM_Channel == TIM_Channel_1) ||(TIM_Channel == TIM_Channel_3))
{
tmp += (TIM_Channel>>1);
/* Reset the OCxM bits in the CCMRx register */
*(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC1M);
/* Configure the OCxM bits in the CCMRx register */
*(__IO uint32_t *) tmp |= TIM_OCMode;
}
else
{
tmp += (uint16_t)(TIM_Channel - (uint16_t)4)>> (uint16_t)1;
/* Reset the OCxM bits in the CCMRx register */
*(__IO uint32_t *) tmp &= (uint32_t)~((uint32_t)TIM_CCMR1_OC2M);
/* Configure the OCxM bits in the CCMRx register */
*(__IO uint32_t *) tmp |= (uint16_t)(TIM_OCMode << 8);
}
}
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
/**
* @brief Enables or Disables the TIMx Update event.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param NewState: new state of the TIMx UDIS bit
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_UpdateDisableConfig(TIM_TypeDef* TIMx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Set the Update Disable Bit */
TIMx->CR1 |= TIM_CR1_UDIS;
}
else
{
/* Reset the Update Disable Bit */
TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_UDIS);
}
}
/**
* @brief Configures the TIMx Update Request Interrupt source.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param TIM_UpdateSource: specifies the Update source.
* This parameter can be one of the following values:
* @arg TIM_UpdateSource_Regular: Source of update is the counter overflow/underflow
or the setting of UG bit, or an update generation
through the slave mode controller.
* @arg TIM_UpdateSource_Global: Source of update is counter overflow/underflow.
* @retval None
*/
void TIM_UpdateRequestConfig(TIM_TypeDef* TIMx, uint16_t TIM_UpdateSource)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_UPDATE_SOURCE(TIM_UpdateSource));
if (TIM_UpdateSource != TIM_UpdateSource_Global)
{
/* Set the URS Bit */
TIMx->CR1 |= TIM_CR1_URS;
}
else
{
/* Reset the URS Bit */
TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_URS);
}
}
/**
* @brief Enables or disables the TIMx's Hall sensor interface.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param NewState: new state of the TIMx Hall sensor interface.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void TIM_SelectHallSensor(TIM_TypeDef* TIMx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Set the TI1S Bit */
TIMx->CR2 |= TIM_CR2_TI1S;
}
else
{
/* Reset the TI1S Bit */
TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_TI1S);
}
}
/**
* @brief Selects the TIMx's One Pulse Mode.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param TIM_OPMode: specifies the OPM Mode to be used.
* This parameter can be one of the following values:
* @arg TIM_OPMode_Single
* @arg TIM_OPMode_Repetitive
* @retval None
*/
void TIM_SelectOnePulseMode(TIM_TypeDef* TIMx, uint16_t TIM_OPMode)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_OPM_MODE(TIM_OPMode));
/* Reset the OPM Bit */
TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_OPM);
/* Configure the OPM Mode */
TIMx->CR1 |= TIM_OPMode;
}
/**
* @brief Selects the TIMx Trigger Output Mode.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 6, 7, 8, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_TRGOSource: specifies the Trigger Output source.
* This paramter can be one of the following values:
*
* - For all TIMx
* @arg TIM_TRGOSource_Reset: The UG bit in the TIM_EGR register is used as the trigger output (TRGO).
* @arg TIM_TRGOSource_Enable: The Counter Enable CEN is used as the trigger output (TRGO).
* @arg TIM_TRGOSource_Update: The update event is selected as the trigger output (TRGO).
*
* - For all TIMx except TIM6 and TIM7
* @arg TIM_TRGOSource_OC1: The trigger output sends a positive pulse when the CC1IF flag
* is to be set, as soon as a capture or compare match occurs (TRGO).
* @arg TIM_TRGOSource_OC1Ref: OC1REF signal is used as the trigger output (TRGO).
* @arg TIM_TRGOSource_OC2Ref: OC2REF signal is used as the trigger output (TRGO).
* @arg TIM_TRGOSource_OC3Ref: OC3REF signal is used as the trigger output (TRGO).
* @arg TIM_TRGOSource_OC4Ref: OC4REF signal is used as the trigger output (TRGO).
*
* @retval None
*/
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource)
{
/* Check the parameters */
assert_param(IS_TIM_LIST7_PERIPH(TIMx));
assert_param(IS_TIM_TRGO_SOURCE(TIM_TRGOSource));
/* Reset the MMS Bits */
TIMx->CR2 &= (uint16_t)~((uint16_t)TIM_CR2_MMS);
/* Select the TRGO source */
TIMx->CR2 |= TIM_TRGOSource;
}
/**
* @brief Selects the TIMx Slave Mode.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_SlaveMode: specifies the Timer Slave Mode.
* This parameter can be one of the following values:
* @arg TIM_SlaveMode_Reset: Rising edge of the selected trigger signal (TRGI) re-initializes
* the counter and triggers an update of the registers.
* @arg TIM_SlaveMode_Gated: The counter clock is enabled when the trigger signal (TRGI) is high.
* @arg TIM_SlaveMode_Trigger: The counter starts at a rising edge of the trigger TRGI.
* @arg TIM_SlaveMode_External1: Rising edges of the selected trigger (TRGI) clock the counter.
* @retval None
*/
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode)
{
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_SLAVE_MODE(TIM_SlaveMode));
/* Reset the SMS Bits */
TIMx->SMCR &= (uint16_t)~((uint16_t)TIM_SMCR_SMS);
/* Select the Slave Mode */
TIMx->SMCR |= TIM_SlaveMode;
}
/**
* @brief Sets or Resets the TIMx Master/Slave Mode.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_MasterSlaveMode: specifies the Timer Master Slave Mode.
* This parameter can be one of the following values:
* @arg TIM_MasterSlaveMode_Enable: synchronization between the current timer
* and its slaves (through TRGO).
* @arg TIM_MasterSlaveMode_Disable: No action
* @retval None
*/
void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_MasterSlaveMode)
{
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_MSM_STATE(TIM_MasterSlaveMode));
/* Reset the MSM Bit */
TIMx->SMCR &= (uint16_t)~((uint16_t)TIM_SMCR_MSM);
/* Set or Reset the MSM Bit */
TIMx->SMCR |= TIM_MasterSlaveMode;
}
/**
* @brief Sets the TIMx Counter Register value
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param Counter: specifies the Counter register new value.
* @retval None
*/
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
/* Set the Counter Register value */
TIMx->CNT = Counter;
}
/**
* @brief Sets the TIMx Autoreload Register value
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param Autoreload: specifies the Autoreload register new value.
* @retval None
*/
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
/* Set the Autoreload Register value */
TIMx->ARR = Autoreload;
}
/**
* @brief Sets the TIMx Capture Compare1 Register value
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param Compare1: specifies the Capture Compare1 register new value.
* @retval None
*/
void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)
{
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
/* Set the Capture Compare1 Register value */
TIMx->CCR1 = Compare1;
}
/**
* @brief Sets the TIMx Capture Compare2 Register value
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @param Compare2: specifies the Capture Compare2 register new value.
* @retval None
*/
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2)
{
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
/* Set the Capture Compare2 Register value */
TIMx->CCR2 = Compare2;
}
/**
* @brief Sets the TIMx Capture Compare3 Register value
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param Compare3: specifies the Capture Compare3 register new value.
* @retval None
*/
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3)
{
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
/* Set the Capture Compare3 Register value */
TIMx->CCR3 = Compare3;
}
/**
* @brief Sets the TIMx Capture Compare4 Register value
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param Compare4: specifies the Capture Compare4 register new value.
* @retval None
*/
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4)
{
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
/* Set the Capture Compare4 Register value */
TIMx->CCR4 = Compare4;
}
/**
* @brief Sets the TIMx Input Capture 1 prescaler.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_ICPSC: specifies the Input Capture1 prescaler new value.
* This parameter can be one of the following values:
* @arg TIM_ICPSC_DIV1: no prescaler
* @arg TIM_ICPSC_DIV2: capture is done once every 2 events
* @arg TIM_ICPSC_DIV4: capture is done once every 4 events
* @arg TIM_ICPSC_DIV8: capture is done once every 8 events
* @retval None
*/
void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC)
{
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC));
/* Reset the IC1PSC Bits */
TIMx->CCMR1 &= (uint16_t)~((uint16_t)TIM_CCMR1_IC1PSC);
/* Set the IC1PSC value */
TIMx->CCMR1 |= TIM_ICPSC;
}
/**
* @brief Sets the TIMx Input Capture 2 prescaler.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_ICPSC: specifies the Input Capture2 prescaler new value.
* This parameter can be one of the following values:
* @arg TIM_ICPSC_DIV1: no prescaler
* @arg TIM_ICPSC_DIV2: capture is done once every 2 events
* @arg TIM_ICPSC_DIV4: capture is done once every 4 events
* @arg TIM_ICPSC_DIV8: capture is done once every 8 events
* @retval None
*/
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC)
{
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC));
/* Reset the IC2PSC Bits */
TIMx->CCMR1 &= (uint16_t)~((uint16_t)TIM_CCMR1_IC2PSC);
/* Set the IC2PSC value */
TIMx->CCMR1 |= (uint16_t)(TIM_ICPSC << 8);
}
/**
* @brief Sets the TIMx Input Capture 3 prescaler.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_ICPSC: specifies the Input Capture3 prescaler new value.
* This parameter can be one of the following values:
* @arg TIM_ICPSC_DIV1: no prescaler
* @arg TIM_ICPSC_DIV2: capture is done once every 2 events
* @arg TIM_ICPSC_DIV4: capture is done once every 4 events
* @arg TIM_ICPSC_DIV8: capture is done once every 8 events
* @retval None
*/
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC)
{
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC));
/* Reset the IC3PSC Bits */
TIMx->CCMR2 &= (uint16_t)~((uint16_t)TIM_CCMR2_IC3PSC);
/* Set the IC3PSC value */
TIMx->CCMR2 |= TIM_ICPSC;
}
/**
* @brief Sets the TIMx Input Capture 4 prescaler.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_ICPSC: specifies the Input Capture4 prescaler new value.
* This parameter can be one of the following values:
* @arg TIM_ICPSC_DIV1: no prescaler
* @arg TIM_ICPSC_DIV2: capture is done once every 2 events
* @arg TIM_ICPSC_DIV4: capture is done once every 4 events
* @arg TIM_ICPSC_DIV8: capture is done once every 8 events
* @retval None
*/
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC)
{
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
assert_param(IS_TIM_IC_PRESCALER(TIM_ICPSC));
/* Reset the IC4PSC Bits */
TIMx->CCMR2 &= (uint16_t)~((uint16_t)TIM_CCMR2_IC4PSC);
/* Set the IC4PSC value */
TIMx->CCMR2 |= (uint16_t)(TIM_ICPSC << 8);
}
/**
* @brief Sets the TIMx Clock Division value.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select
* the TIM peripheral.
* @param TIM_CKD: specifies the clock division value.
* This parameter can be one of the following value:
* @arg TIM_CKD_DIV1: TDTS = Tck_tim
* @arg TIM_CKD_DIV2: TDTS = 2*Tck_tim
* @arg TIM_CKD_DIV4: TDTS = 4*Tck_tim
* @retval None
*/
void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD)
{
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
assert_param(IS_TIM_CKD_DIV(TIM_CKD));
/* Reset the CKD Bits */
TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_CKD);
/* Set the CKD value */
TIMx->CR1 |= TIM_CKD;
}
/**
* @brief Gets the TIMx Input Capture 1 value.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @retval Capture Compare 1 Register value.
*/
uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx)
{
/* Check the parameters */
assert_param(IS_TIM_LIST8_PERIPH(TIMx));
/* Get the Capture 1 Register value */
return TIMx->CCR1;
}
/**
* @brief Gets the TIMx Input Capture 2 value.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @retval Capture Compare 2 Register value.
*/
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx)
{
/* Check the parameters */
assert_param(IS_TIM_LIST6_PERIPH(TIMx));
/* Get the Capture 2 Register value */
return TIMx->CCR2;
}
/**
* @brief Gets the TIMx Input Capture 3 value.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @retval Capture Compare 3 Register value.
*/
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx)
{
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
/* Get the Capture 3 Register value */
return TIMx->CCR3;
}
/**
* @brief Gets the TIMx Input Capture 4 value.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @retval Capture Compare 4 Register value.
*/
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx)
{
/* Check the parameters */
assert_param(IS_TIM_LIST3_PERIPH(TIMx));
/* Get the Capture 4 Register value */
return TIMx->CCR4;
}
/**
* @brief Gets the TIMx Counter value.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @retval Counter Register value.
*/
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
/* Get the Counter Register value */
return TIMx->CNT;
}
/**
* @brief Gets the TIMx Prescaler value.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @retval Prescaler Register value.
*/
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
/* Get the Prescaler Register value */
return TIMx->PSC;
}
/**
* @brief Checks whether the specified TIM flag is set or not.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param TIM_FLAG: specifies the flag to check.
* This parameter can be one of the following values:
* @arg TIM_FLAG_Update: TIM update Flag
* @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag
* @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag
* @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag
* @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag
* @arg TIM_FLAG_COM: TIM Commutation Flag
* @arg TIM_FLAG_Trigger: TIM Trigger Flag
* @arg TIM_FLAG_Break: TIM Break Flag
* @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag
* @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag
* @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag
* @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag
* @note
* - TIM6 and TIM7 can have only one update flag.
* - TIM9, TIM12 and TIM15 can have only TIM_FLAG_Update, TIM_FLAG_CC1,
* TIM_FLAG_CC2 or TIM_FLAG_Trigger.
* - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_FLAG_Update or TIM_FLAG_CC1.
* - TIM_FLAG_Break is used only with TIM1, TIM8 and TIM15.
* - TIM_FLAG_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.
* @retval The new state of TIM_FLAG (SET or RESET).
*/
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
{
ITStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_GET_FLAG(TIM_FLAG));
if ((TIMx->SR & TIM_FLAG) != (uint16_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the TIMx's pending flags.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param TIM_FLAG: specifies the flag bit to clear.
* This parameter can be any combination of the following values:
* @arg TIM_FLAG_Update: TIM update Flag
* @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag
* @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag
* @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag
* @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag
* @arg TIM_FLAG_COM: TIM Commutation Flag
* @arg TIM_FLAG_Trigger: TIM Trigger Flag
* @arg TIM_FLAG_Break: TIM Break Flag
* @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag
* @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag
* @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag
* @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag
* @note
* - TIM6 and TIM7 can have only one update flag.
* - TIM9, TIM12 and TIM15 can have only TIM_FLAG_Update, TIM_FLAG_CC1,
* TIM_FLAG_CC2 or TIM_FLAG_Trigger.
* - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_FLAG_Update or TIM_FLAG_CC1.
* - TIM_FLAG_Break is used only with TIM1, TIM8 and TIM15.
* - TIM_FLAG_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.
* @retval None
*/
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_CLEAR_FLAG(TIM_FLAG));
/* Clear the flags */
TIMx->SR = (uint16_t)~TIM_FLAG;
}
/**
* @brief Checks whether the TIM interrupt has occurred or not.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param TIM_IT: specifies the TIM interrupt source to check.
* This parameter can be one of the following values:
* @arg TIM_IT_Update: TIM update Interrupt source
* @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
* @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
* @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
* @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
* @arg TIM_IT_COM: TIM Commutation Interrupt source
* @arg TIM_IT_Trigger: TIM Trigger Interrupt source
* @arg TIM_IT_Break: TIM Break Interrupt source
* @note
* - TIM6 and TIM7 can generate only an update interrupt.
* - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,
* TIM_IT_CC2 or TIM_IT_Trigger.
* - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.
* - TIM_IT_Break is used only with TIM1, TIM8 and TIM15.
* - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.
* @retval The new state of the TIM_IT(SET or RESET).
*/
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT)
{
ITStatus bitstatus = RESET;
uint16_t itstatus = 0x0, itenable = 0x0;
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_GET_IT(TIM_IT));
itstatus = TIMx->SR & TIM_IT;
itenable = TIMx->DIER & TIM_IT;
if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the TIMx's interrupt pending bits.
* @param TIMx: where x can be 1 to 17 to select the TIM peripheral.
* @param TIM_IT: specifies the pending bit to clear.
* This parameter can be any combination of the following values:
* @arg TIM_IT_Update: TIM1 update Interrupt source
* @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
* @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
* @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
* @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
* @arg TIM_IT_COM: TIM Commutation Interrupt source
* @arg TIM_IT_Trigger: TIM Trigger Interrupt source
* @arg TIM_IT_Break: TIM Break Interrupt source
* @note
* - TIM6 and TIM7 can generate only an update interrupt.
* - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,
* TIM_IT_CC2 or TIM_IT_Trigger.
* - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.
* - TIM_IT_Break is used only with TIM1, TIM8 and TIM15.
* - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.
* @retval None
*/
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
{
/* Check the parameters */
assert_param(IS_TIM_ALL_PERIPH(TIMx));
assert_param(IS_TIM_IT(TIM_IT));
/* Clear the IT pending Bit */
TIMx->SR = (uint16_t)~TIM_IT;
}
/**
* @brief Configure the TI1 as Input.
* @param TIMx: where x can be 1 to 17 except 6 and 7 to select the TIM peripheral.
* @param TIM_ICPolarity : The Input Polarity.
* This parameter can be one of the following values:
* @arg TIM_ICPolarity_Rising
* @arg TIM_ICPolarity_Falling
* @param TIM_ICSelection: specifies the input to be used.
* This parameter can be one of the following values:
* @arg TIM_ICSelection_DirectTI: TIM Input 1 is selected to be connected to IC1.
* @arg TIM_ICSelection_IndirectTI: TIM Input 1 is selected to be connected to IC2.
* @arg TIM_ICSelection_TRC: TIM Input 1 is selected to be connected to TRC.
* @param TIM_ICFilter: Specifies the Input Capture Filter.
* This parameter must be a value between 0x00 and 0x0F.
* @retval None
*/
static void TI1_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection,
uint16_t TIM_ICFilter)
{
uint16_t tmpccmr1 = 0, tmpccer = 0;
/* Disable the Channel 1: Reset the CC1E Bit */
TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC1E);
tmpccmr1 = TIMx->CCMR1;
tmpccer = TIMx->CCER;
/* Select the Input and set the filter */
tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC1S)) & ((uint16_t)~((uint16_t)TIM_CCMR1_IC1F)));
tmpccmr1 |= (uint16_t)(TIM_ICSelection | (uint16_t)(TIM_ICFilter << (uint16_t)4));
if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) ||
(TIMx == TIM4) ||(TIMx == TIM5))
{
/* Select the Polarity and set the CC1E Bit */
tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC1P));
tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC1E);
}
else
{
/* Select the Polarity and set the CC1E Bit */
tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC1P | TIM_CCER_CC1NP));
tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC1E);
}
/* Write to TIMx CCMR1 and CCER registers */
TIMx->CCMR1 = tmpccmr1;
TIMx->CCER = tmpccer;
}
/**
* @brief Configure the TI2 as Input.
* @param TIMx: where x can be 1, 2, 3, 4, 5, 8, 9, 12 or 15 to select the TIM peripheral.
* @param TIM_ICPolarity : The Input Polarity.
* This parameter can be one of the following values:
* @arg TIM_ICPolarity_Rising
* @arg TIM_ICPolarity_Falling
* @param TIM_ICSelection: specifies the input to be used.
* This parameter can be one of the following values:
* @arg TIM_ICSelection_DirectTI: TIM Input 2 is selected to be connected to IC2.
* @arg TIM_ICSelection_IndirectTI: TIM Input 2 is selected to be connected to IC1.
* @arg TIM_ICSelection_TRC: TIM Input 2 is selected to be connected to TRC.
* @param TIM_ICFilter: Specifies the Input Capture Filter.
* This parameter must be a value between 0x00 and 0x0F.
* @retval None
*/
static void TI2_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection,
uint16_t TIM_ICFilter)
{
uint16_t tmpccmr1 = 0, tmpccer = 0, tmp = 0;
/* Disable the Channel 2: Reset the CC2E Bit */
TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC2E);
tmpccmr1 = TIMx->CCMR1;
tmpccer = TIMx->CCER;
tmp = (uint16_t)(TIM_ICPolarity << 4);
/* Select the Input and set the filter */
tmpccmr1 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR1_CC2S)) & ((uint16_t)~((uint16_t)TIM_CCMR1_IC2F)));
tmpccmr1 |= (uint16_t)(TIM_ICFilter << 12);
tmpccmr1 |= (uint16_t)(TIM_ICSelection << 8);
if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) ||
(TIMx == TIM4) ||(TIMx == TIM5))
{
/* Select the Polarity and set the CC2E Bit */
tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC2P));
tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC2E);
}
else
{
/* Select the Polarity and set the CC2E Bit */
tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC2P | TIM_CCER_CC2NP));
tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC2E);
}
/* Write to TIMx CCMR1 and CCER registers */
TIMx->CCMR1 = tmpccmr1 ;
TIMx->CCER = tmpccer;
}
/**
* @brief Configure the TI3 as Input.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_ICPolarity : The Input Polarity.
* This parameter can be one of the following values:
* @arg TIM_ICPolarity_Rising
* @arg TIM_ICPolarity_Falling
* @param TIM_ICSelection: specifies the input to be used.
* This parameter can be one of the following values:
* @arg TIM_ICSelection_DirectTI: TIM Input 3 is selected to be connected to IC3.
* @arg TIM_ICSelection_IndirectTI: TIM Input 3 is selected to be connected to IC4.
* @arg TIM_ICSelection_TRC: TIM Input 3 is selected to be connected to TRC.
* @param TIM_ICFilter: Specifies the Input Capture Filter.
* This parameter must be a value between 0x00 and 0x0F.
* @retval None
*/
static void TI3_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection,
uint16_t TIM_ICFilter)
{
uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0;
/* Disable the Channel 3: Reset the CC3E Bit */
TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC3E);
tmpccmr2 = TIMx->CCMR2;
tmpccer = TIMx->CCER;
tmp = (uint16_t)(TIM_ICPolarity << 8);
/* Select the Input and set the filter */
tmpccmr2 &= (uint16_t)(((uint16_t)~((uint16_t)TIM_CCMR2_CC3S)) & ((uint16_t)~((uint16_t)TIM_CCMR2_IC3F)));
tmpccmr2 |= (uint16_t)(TIM_ICSelection | (uint16_t)(TIM_ICFilter << (uint16_t)4));
if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) ||
(TIMx == TIM4) ||(TIMx == TIM5))
{
/* Select the Polarity and set the CC3E Bit */
tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P));
tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC3E);
}
else
{
/* Select the Polarity and set the CC3E Bit */
tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P | TIM_CCER_CC3NP));
tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC3E);
}
/* Write to TIMx CCMR2 and CCER registers */
TIMx->CCMR2 = tmpccmr2;
TIMx->CCER = tmpccer;
}
/**
* @brief Configure the TI4 as Input.
* @param TIMx: where x can be 1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
* @param TIM_ICPolarity : The Input Polarity.
* This parameter can be one of the following values:
* @arg TIM_ICPolarity_Rising
* @arg TIM_ICPolarity_Falling
* @param TIM_ICSelection: specifies the input to be used.
* This parameter can be one of the following values:
* @arg TIM_ICSelection_DirectTI: TIM Input 4 is selected to be connected to IC4.
* @arg TIM_ICSelection_IndirectTI: TIM Input 4 is selected to be connected to IC3.
* @arg TIM_ICSelection_TRC: TIM Input 4 is selected to be connected to TRC.
* @param TIM_ICFilter: Specifies the Input Capture Filter.
* This parameter must be a value between 0x00 and 0x0F.
* @retval None
*/
static void TI4_Config(TIM_TypeDef* TIMx, uint16_t TIM_ICPolarity, uint16_t TIM_ICSelection,
uint16_t TIM_ICFilter)
{
uint16_t tmpccmr2 = 0, tmpccer = 0, tmp = 0;
/* Disable the Channel 4: Reset the CC4E Bit */
TIMx->CCER &= (uint16_t)~((uint16_t)TIM_CCER_CC4E);
tmpccmr2 = TIMx->CCMR2;
tmpccer = TIMx->CCER;
tmp = (uint16_t)(TIM_ICPolarity << 12);
/* Select the Input and set the filter */
tmpccmr2 &= (uint16_t)((uint16_t)(~(uint16_t)TIM_CCMR2_CC4S) & ((uint16_t)~((uint16_t)TIM_CCMR2_IC4F)));
tmpccmr2 |= (uint16_t)(TIM_ICSelection << 8);
tmpccmr2 |= (uint16_t)(TIM_ICFilter << 12);
if((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) ||
(TIMx == TIM4) ||(TIMx == TIM5))
{
/* Select the Polarity and set the CC4E Bit */
tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC4P));
tmpccer |= (uint16_t)(tmp | (uint16_t)TIM_CCER_CC4E);
}
else
{
/* Select the Polarity and set the CC4E Bit */
tmpccer &= (uint16_t)~((uint16_t)(TIM_CCER_CC3P | TIM_CCER_CC4NP));
tmpccer |= (uint16_t)(TIM_ICPolarity | (uint16_t)TIM_CCER_CC4E);
}
/* Write to TIMx CCMR2 and CCER registers */
TIMx->CCMR2 = tmpccmr2;
TIMx->CCER = tmpccer;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_usart.c
================================================
/**
******************************************************************************
* @file stm32f10x_usart.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the USART firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f10x_usart.h"
#include "stm32f10x_rcc.h"
/** @addtogroup STM32F10x_StdPeriph_Driver
* @{
*/
/** @defgroup USART
* @brief USART driver modules
* @{
*/
/** @defgroup USART_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup USART_Private_Defines
* @{
*/
#define CR1_UE_Set ((uint16_t)0x2000) /*!< USART Enable Mask */
#define CR1_UE_Reset ((uint16_t)0xDFFF) /*!< USART Disable Mask */
#define CR1_WAKE_Mask ((uint16_t)0xF7FF) /*!< USART WakeUp Method Mask */
#define CR1_RWU_Set ((uint16_t)0x0002) /*!< USART mute mode Enable Mask */
#define CR1_RWU_Reset ((uint16_t)0xFFFD) /*!< USART mute mode Enable Mask */
#define CR1_SBK_Set ((uint16_t)0x0001) /*!< USART Break Character send Mask */
#define CR1_CLEAR_Mask ((uint16_t)0xE9F3) /*!< USART CR1 Mask */
#define CR2_Address_Mask ((uint16_t)0xFFF0) /*!< USART address Mask */
#define CR2_LINEN_Set ((uint16_t)0x4000) /*!< USART LIN Enable Mask */
#define CR2_LINEN_Reset ((uint16_t)0xBFFF) /*!< USART LIN Disable Mask */
#define CR2_LBDL_Mask ((uint16_t)0xFFDF) /*!< USART LIN Break detection Mask */
#define CR2_STOP_CLEAR_Mask ((uint16_t)0xCFFF) /*!< USART CR2 STOP Bits Mask */
#define CR2_CLOCK_CLEAR_Mask ((uint16_t)0xF0FF) /*!< USART CR2 Clock Mask */
#define CR3_SCEN_Set ((uint16_t)0x0020) /*!< USART SC Enable Mask */
#define CR3_SCEN_Reset ((uint16_t)0xFFDF) /*!< USART SC Disable Mask */
#define CR3_NACK_Set ((uint16_t)0x0010) /*!< USART SC NACK Enable Mask */
#define CR3_NACK_Reset ((uint16_t)0xFFEF) /*!< USART SC NACK Disable Mask */
#define CR3_HDSEL_Set ((uint16_t)0x0008) /*!< USART Half-Duplex Enable Mask */
#define CR3_HDSEL_Reset ((uint16_t)0xFFF7) /*!< USART Half-Duplex Disable Mask */
#define CR3_IRLP_Mask ((uint16_t)0xFFFB) /*!< USART IrDA LowPower mode Mask */
#define CR3_CLEAR_Mask ((uint16_t)0xFCFF) /*!< USART CR3 Mask */
#define CR3_IREN_Set ((uint16_t)0x0002) /*!< USART IrDA Enable Mask */
#define CR3_IREN_Reset ((uint16_t)0xFFFD) /*!< USART IrDA Disable Mask */
#define GTPR_LSB_Mask ((uint16_t)0x00FF) /*!< Guard Time Register LSB Mask */
#define GTPR_MSB_Mask ((uint16_t)0xFF00) /*!< Guard Time Register MSB Mask */
#define IT_Mask ((uint16_t)0x001F) /*!< USART Interrupt Mask */
/* USART OverSampling-8 Mask */
#define CR1_OVER8_Set ((u16)0x8000) /* USART OVER8 mode Enable Mask */
#define CR1_OVER8_Reset ((u16)0x7FFF) /* USART OVER8 mode Disable Mask */
/* USART One Bit Sampling Mask */
#define CR3_ONEBITE_Set ((u16)0x0800) /* USART ONEBITE mode Enable Mask */
#define CR3_ONEBITE_Reset ((u16)0xF7FF) /* USART ONEBITE mode Disable Mask */
/**
* @}
*/
/** @defgroup USART_Private_Macros
* @{
*/
/**
* @}
*/
/** @defgroup USART_Private_Variables
* @{
*/
/**
* @}
*/
/** @defgroup USART_Private_FunctionPrototypes
* @{
*/
/**
* @}
*/
/** @defgroup USART_Private_Functions
* @{
*/
/**
* @brief Deinitializes the USARTx peripheral registers to their default reset values.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @retval None
*/
void USART_DeInit(USART_TypeDef* USARTx)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
if (USARTx == USART1)
{
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_USART1, DISABLE);
}
else if (USARTx == USART2)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART2, DISABLE);
}
else if (USARTx == USART3)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_USART3, DISABLE);
}
else if (USARTx == UART4)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART4, DISABLE);
}
else
{
if (USARTx == UART5)
{
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, ENABLE);
RCC_APB1PeriphResetCmd(RCC_APB1Periph_UART5, DISABLE);
}
}
}
/**
* @brief Initializes the USARTx peripheral according to the specified
* parameters in the USART_InitStruct .
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_InitStruct: pointer to a USART_InitTypeDef structure
* that contains the configuration information for the specified USART
* peripheral.
* @retval None
*/
void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct)
{
uint32_t tmpreg = 0x00, apbclock = 0x00;
uint32_t integerdivider = 0x00;
uint32_t fractionaldivider = 0x00;
uint32_t usartxbase = 0;
RCC_ClocksTypeDef RCC_ClocksStatus;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_BAUDRATE(USART_InitStruct->USART_BaudRate));
assert_param(IS_USART_WORD_LENGTH(USART_InitStruct->USART_WordLength));
assert_param(IS_USART_STOPBITS(USART_InitStruct->USART_StopBits));
assert_param(IS_USART_PARITY(USART_InitStruct->USART_Parity));
assert_param(IS_USART_MODE(USART_InitStruct->USART_Mode));
assert_param(IS_USART_HARDWARE_FLOW_CONTROL(USART_InitStruct->USART_HardwareFlowControl));
/* The hardware flow control is available only for USART1, USART2 and USART3 */
if (USART_InitStruct->USART_HardwareFlowControl != USART_HardwareFlowControl_None)
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
usartxbase = (uint32_t)USARTx;
/*---------------------------- USART CR2 Configuration -----------------------*/
tmpreg = USARTx->CR2;
/* Clear STOP[13:12] bits */
tmpreg &= CR2_STOP_CLEAR_Mask;
/* Configure the USART Stop Bits, Clock, CPOL, CPHA and LastBit ------------*/
/* Set STOP[13:12] bits according to USART_StopBits value */
tmpreg |= (uint32_t)USART_InitStruct->USART_StopBits;
/* Write to USART CR2 */
USARTx->CR2 = (uint16_t)tmpreg;
/*---------------------------- USART CR1 Configuration -----------------------*/
tmpreg = USARTx->CR1;
/* Clear M, PCE, PS, TE and RE bits */
tmpreg &= CR1_CLEAR_Mask;
/* Configure the USART Word Length, Parity and mode ----------------------- */
/* Set the M bits according to USART_WordLength value */
/* Set PCE and PS bits according to USART_Parity value */
/* Set TE and RE bits according to USART_Mode value */
tmpreg |= (uint32_t)USART_InitStruct->USART_WordLength | USART_InitStruct->USART_Parity |
USART_InitStruct->USART_Mode;
/* Write to USART CR1 */
USARTx->CR1 = (uint16_t)tmpreg;
/*---------------------------- USART CR3 Configuration -----------------------*/
tmpreg = USARTx->CR3;
/* Clear CTSE and RTSE bits */
tmpreg &= CR3_CLEAR_Mask;
/* Configure the USART HFC -------------------------------------------------*/
/* Set CTSE and RTSE bits according to USART_HardwareFlowControl value */
tmpreg |= USART_InitStruct->USART_HardwareFlowControl;
/* Write to USART CR3 */
USARTx->CR3 = (uint16_t)tmpreg;
/*---------------------------- USART BRR Configuration -----------------------*/
/* Configure the USART Baud Rate -------------------------------------------*/
RCC_GetClocksFreq(&RCC_ClocksStatus);
if (usartxbase == USART1_BASE)
{
apbclock = RCC_ClocksStatus.PCLK2_Frequency;
}
else
{
apbclock = RCC_ClocksStatus.PCLK1_Frequency;
}
/* Determine the integer part */
if ((USARTx->CR1 & CR1_OVER8_Set) != 0)
{
/* Integer part computing in case Oversampling mode is 8 Samples */
integerdivider = ((25 * apbclock) / (2 * (USART_InitStruct->USART_BaudRate)));
}
else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */
{
/* Integer part computing in case Oversampling mode is 16 Samples */
integerdivider = ((25 * apbclock) / (4 * (USART_InitStruct->USART_BaudRate)));
}
tmpreg = (integerdivider / 100) << 4;
/* Determine the fractional part */
fractionaldivider = integerdivider - (100 * (tmpreg >> 4));
/* Implement the fractional part in the register */
if ((USARTx->CR1 & CR1_OVER8_Set) != 0)
{
tmpreg |= ((((fractionaldivider * 8) + 50) / 100)) & ((uint8_t)0x07);
}
else /* if ((USARTx->CR1 & CR1_OVER8_Set) == 0) */
{
tmpreg |= ((((fractionaldivider * 16) + 50) / 100)) & ((uint8_t)0x0F);
}
/* Write to USART BRR */
USARTx->BRR = (uint16_t)tmpreg;
}
/**
* @brief Fills each USART_InitStruct member with its default value.
* @param USART_InitStruct: pointer to a USART_InitTypeDef structure
* which will be initialized.
* @retval None
*/
void USART_StructInit(USART_InitTypeDef* USART_InitStruct)
{
/* USART_InitStruct members default value */
USART_InitStruct->USART_BaudRate = 9600;
USART_InitStruct->USART_WordLength = USART_WordLength_8b;
USART_InitStruct->USART_StopBits = USART_StopBits_1;
USART_InitStruct->USART_Parity = USART_Parity_No ;
USART_InitStruct->USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStruct->USART_HardwareFlowControl = USART_HardwareFlowControl_None;
}
/**
* @brief Initializes the USARTx peripheral Clock according to the
* specified parameters in the USART_ClockInitStruct .
* @param USARTx: where x can be 1, 2, 3 to select the USART peripheral.
* @param USART_ClockInitStruct: pointer to a USART_ClockInitTypeDef
* structure that contains the configuration information for the specified
* USART peripheral.
* @note The Smart Card and Synchronous modes are not available for UART4 and UART5.
* @retval None
*/
void USART_ClockInit(USART_TypeDef* USARTx, USART_ClockInitTypeDef* USART_ClockInitStruct)
{
uint32_t tmpreg = 0x00;
/* Check the parameters */
assert_param(IS_USART_123_PERIPH(USARTx));
assert_param(IS_USART_CLOCK(USART_ClockInitStruct->USART_Clock));
assert_param(IS_USART_CPOL(USART_ClockInitStruct->USART_CPOL));
assert_param(IS_USART_CPHA(USART_ClockInitStruct->USART_CPHA));
assert_param(IS_USART_LASTBIT(USART_ClockInitStruct->USART_LastBit));
/*---------------------------- USART CR2 Configuration -----------------------*/
tmpreg = USARTx->CR2;
/* Clear CLKEN, CPOL, CPHA and LBCL bits */
tmpreg &= CR2_CLOCK_CLEAR_Mask;
/* Configure the USART Clock, CPOL, CPHA and LastBit ------------*/
/* Set CLKEN bit according to USART_Clock value */
/* Set CPOL bit according to USART_CPOL value */
/* Set CPHA bit according to USART_CPHA value */
/* Set LBCL bit according to USART_LastBit value */
tmpreg |= (uint32_t)USART_ClockInitStruct->USART_Clock | USART_ClockInitStruct->USART_CPOL |
USART_ClockInitStruct->USART_CPHA | USART_ClockInitStruct->USART_LastBit;
/* Write to USART CR2 */
USARTx->CR2 = (uint16_t)tmpreg;
}
/**
* @brief Fills each USART_ClockInitStruct member with its default value.
* @param USART_ClockInitStruct: pointer to a USART_ClockInitTypeDef
* structure which will be initialized.
* @retval None
*/
void USART_ClockStructInit(USART_ClockInitTypeDef* USART_ClockInitStruct)
{
/* USART_ClockInitStruct members default value */
USART_ClockInitStruct->USART_Clock = USART_Clock_Disable;
USART_ClockInitStruct->USART_CPOL = USART_CPOL_Low;
USART_ClockInitStruct->USART_CPHA = USART_CPHA_1Edge;
USART_ClockInitStruct->USART_LastBit = USART_LastBit_Disable;
}
/**
* @brief Enables or disables the specified USART peripheral.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param NewState: new state of the USARTx peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected USART by setting the UE bit in the CR1 register */
USARTx->CR1 |= CR1_UE_Set;
}
else
{
/* Disable the selected USART by clearing the UE bit in the CR1 register */
USARTx->CR1 &= CR1_UE_Reset;
}
}
/**
* @brief Enables or disables the specified USART interrupts.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_IT: specifies the USART interrupt sources to be enabled or disabled.
* This parameter can be one of the following values:
* @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5)
* @arg USART_IT_LBD: LIN Break detection interrupt
* @arg USART_IT_TXE: Transmit Data Register empty interrupt
* @arg USART_IT_TC: Transmission complete interrupt
* @arg USART_IT_RXNE: Receive Data register not empty interrupt
* @arg USART_IT_IDLE: Idle line detection interrupt
* @arg USART_IT_PE: Parity Error interrupt
* @arg USART_IT_ERR: Error interrupt(Frame error, noise error, overrun error)
* @param NewState: new state of the specified USARTx interrupts.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState)
{
uint32_t usartreg = 0x00, itpos = 0x00, itmask = 0x00;
uint32_t usartxbase = 0x00;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CONFIG_IT(USART_IT));
assert_param(IS_FUNCTIONAL_STATE(NewState));
/* The CTS interrupt is not available for UART4 and UART5 */
if (USART_IT == USART_IT_CTS)
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
usartxbase = (uint32_t)USARTx;
/* Get the USART register index */
usartreg = (((uint8_t)USART_IT) >> 0x05);
/* Get the interrupt position */
itpos = USART_IT & IT_Mask;
itmask = (((uint32_t)0x01) << itpos);
if (usartreg == 0x01) /* The IT is in CR1 register */
{
usartxbase += 0x0C;
}
else if (usartreg == 0x02) /* The IT is in CR2 register */
{
usartxbase += 0x10;
}
else /* The IT is in CR3 register */
{
usartxbase += 0x14;
}
if (NewState != DISABLE)
{
*(__IO uint32_t*)usartxbase |= itmask;
}
else
{
*(__IO uint32_t*)usartxbase &= ~itmask;
}
}
/**
* @brief Enables or disables the USART�s DMA interface.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_DMAReq: specifies the DMA request.
* This parameter can be any combination of the following values:
* @arg USART_DMAReq_Tx: USART DMA transmit request
* @arg USART_DMAReq_Rx: USART DMA receive request
* @param NewState: new state of the DMA Request sources.
* This parameter can be: ENABLE or DISABLE.
* @note The DMA mode is not available for UART5 except in the STM32
* High density value line devices(STM32F10X_HD_VL).
* @retval None
*/
void USART_DMACmd(USART_TypeDef* USARTx, uint16_t USART_DMAReq, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_DMAREQ(USART_DMAReq));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the DMA transfer for selected requests by setting the DMAT and/or
DMAR bits in the USART CR3 register */
USARTx->CR3 |= USART_DMAReq;
}
else
{
/* Disable the DMA transfer for selected requests by clearing the DMAT and/or
DMAR bits in the USART CR3 register */
USARTx->CR3 &= (uint16_t)~USART_DMAReq;
}
}
/**
* @brief Sets the address of the USART node.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_Address: Indicates the address of the USART node.
* @retval None
*/
void USART_SetAddress(USART_TypeDef* USARTx, uint8_t USART_Address)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_ADDRESS(USART_Address));
/* Clear the USART address */
USARTx->CR2 &= CR2_Address_Mask;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/* Set the USART address node */
USARTx->CR2 |= USART_Address;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
}
/**
* @brief Selects the USART WakeUp method.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_WakeUp: specifies the USART wakeup method.
* This parameter can be one of the following values:
* @arg USART_WakeUp_IdleLine: WakeUp by an idle line detection
* @arg USART_WakeUp_AddressMark: WakeUp by an address mark
* @retval None
*/
void USART_WakeUpConfig(USART_TypeDef* USARTx, uint16_t USART_WakeUp)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_WAKEUP(USART_WakeUp));
USARTx->CR1 &= CR1_WAKE_Mask;
USARTx->CR1 |= USART_WakeUp;
}
/**
* @brief Determines if the USART is in mute mode or not.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param NewState: new state of the USART mute mode.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void USART_ReceiverWakeUpCmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the USART mute mode by setting the RWU bit in the CR1 register */
USARTx->CR1 |= CR1_RWU_Set;
}
else
{
/* Disable the USART mute mode by clearing the RWU bit in the CR1 register */
USARTx->CR1 &= CR1_RWU_Reset;
}
}
/**
* @brief Sets the USART LIN Break detection length.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_LINBreakDetectLength: specifies the LIN break detection length.
* This parameter can be one of the following values:
* @arg USART_LINBreakDetectLength_10b: 10-bit break detection
* @arg USART_LINBreakDetectLength_11b: 11-bit break detection
* @retval None
*/
void USART_LINBreakDetectLengthConfig(USART_TypeDef* USARTx, uint16_t USART_LINBreakDetectLength)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_LIN_BREAK_DETECT_LENGTH(USART_LINBreakDetectLength));
USARTx->CR2 &= CR2_LBDL_Mask;
USARTx->CR2 |= USART_LINBreakDetectLength;
}
/**
* @brief Enables or disables the USART�s LIN mode.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param NewState: new state of the USART LIN mode.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void USART_LINCmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the LIN mode by setting the LINEN bit in the CR2 register */
USARTx->CR2 |= CR2_LINEN_Set;
}
else
{
/* Disable the LIN mode by clearing the LINEN bit in the CR2 register */
USARTx->CR2 &= CR2_LINEN_Reset;
}
}
/**
* @brief Transmits single data through the USARTx peripheral.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param Data: the data to transmit.
* @retval None
*/
void USART_SendData(USART_TypeDef* USARTx, uint16_t Data)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_DATA(Data));
/* Transmit Data */
USARTx->DR = (Data & (uint16_t)0x01FF);
}
/**
* @brief Returns the most recent received data by the USARTx peripheral.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @retval The received data.
*/
uint16_t USART_ReceiveData(USART_TypeDef* USARTx)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
/* Receive Data */
return (uint16_t)(USARTx->DR & (uint16_t)0x01FF);
}
/**
* @brief Transmits break characters.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @retval None
*/
void USART_SendBreak(USART_TypeDef* USARTx)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
/* Send break characters */
USARTx->CR1 |= CR1_SBK_Set;
}
/**
* @brief Sets the specified USART guard time.
* @param USARTx: where x can be 1, 2 or 3 to select the USART peripheral.
* @param USART_GuardTime: specifies the guard time.
* @note The guard time bits are not available for UART4 and UART5.
* @retval None
*/
void USART_SetGuardTime(USART_TypeDef* USARTx, uint8_t USART_GuardTime)
{
/* Check the parameters */
assert_param(IS_USART_123_PERIPH(USARTx));
/* Clear the USART Guard time */
USARTx->GTPR &= GTPR_LSB_Mask;
/* Set the USART guard time */
USARTx->GTPR |= (uint16_t)((uint16_t)USART_GuardTime << 0x08);
}
/**
* @brief Sets the system clock prescaler.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_Prescaler: specifies the prescaler clock.
* @note The function is used for IrDA mode with UART4 and UART5.
* @retval None
*/
void USART_SetPrescaler(USART_TypeDef* USARTx, uint8_t USART_Prescaler)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
/* Clear the USART prescaler */
USARTx->GTPR &= GTPR_MSB_Mask;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
/* Set the USART prescaler */
USARTx->GTPR |= USART_Prescaler;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
}
/**
* @brief Enables or disables the USART�s Smart Card mode.
* @param USARTx: where x can be 1, 2 or 3 to select the USART peripheral.
* @param NewState: new state of the Smart Card mode.
* This parameter can be: ENABLE or DISABLE.
* @note The Smart Card mode is not available for UART4 and UART5.
* @retval None
*/
void USART_SmartCardCmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_123_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the SC mode by setting the SCEN bit in the CR3 register */
USARTx->CR3 |= CR3_SCEN_Set;
}
else
{
/* Disable the SC mode by clearing the SCEN bit in the CR3 register */
USARTx->CR3 &= CR3_SCEN_Reset;
}
}
/**
* @brief Enables or disables NACK transmission.
* @param USARTx: where x can be 1, 2 or 3 to select the USART peripheral.
* @param NewState: new state of the NACK transmission.
* This parameter can be: ENABLE or DISABLE.
* @note The Smart Card mode is not available for UART4 and UART5.
* @retval None
*/
void USART_SmartCardNACKCmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_123_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the NACK transmission by setting the NACK bit in the CR3 register */
USARTx->CR3 |= CR3_NACK_Set;
}
else
{
/* Disable the NACK transmission by clearing the NACK bit in the CR3 register */
USARTx->CR3 &= CR3_NACK_Reset;
}
}
/**
* @brief Enables or disables the USART�s Half Duplex communication.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param NewState: new state of the USART Communication.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void USART_HalfDuplexCmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */
USARTx->CR3 |= CR3_HDSEL_Set;
}
else
{
/* Disable the Half-Duplex mode by clearing the HDSEL bit in the CR3 register */
USARTx->CR3 &= CR3_HDSEL_Reset;
}
}
/**
* @brief Enables or disables the USART's 8x oversampling mode.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param NewState: new state of the USART one bit sampling method.
* This parameter can be: ENABLE or DISABLE.
* @note
* This function has to be called before calling USART_Init()
* function in order to have correct baudrate Divider value.
* @retval None
*/
void USART_OverSampling8Cmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the 8x Oversampling mode by setting the OVER8 bit in the CR1 register */
USARTx->CR1 |= CR1_OVER8_Set;
}
else
{
/* Disable the 8x Oversampling mode by clearing the OVER8 bit in the CR1 register */
USARTx->CR1 &= CR1_OVER8_Reset;
}
}
/**
* @brief Enables or disables the USART's one bit sampling method.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param NewState: new state of the USART one bit sampling method.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void USART_OneBitMethodCmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the one bit method by setting the ONEBITE bit in the CR3 register */
USARTx->CR3 |= CR3_ONEBITE_Set;
}
else
{
/* Disable tthe one bit method by clearing the ONEBITE bit in the CR3 register */
USARTx->CR3 &= CR3_ONEBITE_Reset;
}
}
/**
* @brief Configures the USART's IrDA interface.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_IrDAMode: specifies the IrDA mode.
* This parameter can be one of the following values:
* @arg USART_IrDAMode_LowPower
* @arg USART_IrDAMode_Normal
* @retval None
*/
void USART_IrDAConfig(USART_TypeDef* USARTx, uint16_t USART_IrDAMode)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_IRDA_MODE(USART_IrDAMode));
USARTx->CR3 &= CR3_IRLP_Mask;
USARTx->CR3 |= USART_IrDAMode;
}
/**
* @brief Enables or disables the USART's IrDA interface.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param NewState: new state of the IrDA mode.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void USART_IrDACmd(USART_TypeDef* USARTx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the IrDA mode by setting the IREN bit in the CR3 register */
USARTx->CR3 |= CR3_IREN_Set;
}
else
{
/* Disable the IrDA mode by clearing the IREN bit in the CR3 register */
USARTx->CR3 &= CR3_IREN_Reset;
}
}
/**
* @brief Checks whether the specified USART flag is set or not.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_FLAG: specifies the flag to check.
* This parameter can be one of the following values:
* @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5)
* @arg USART_FLAG_LBD: LIN Break detection flag
* @arg USART_FLAG_TXE: Transmit data register empty flag
* @arg USART_FLAG_TC: Transmission Complete flag
* @arg USART_FLAG_RXNE: Receive data register not empty flag
* @arg USART_FLAG_IDLE: Idle Line detection flag
* @arg USART_FLAG_ORE: OverRun Error flag
* @arg USART_FLAG_NE: Noise Error flag
* @arg USART_FLAG_FE: Framing Error flag
* @arg USART_FLAG_PE: Parity Error flag
* @retval The new state of USART_FLAG (SET or RESET).
*/
FlagStatus USART_GetFlagStatus(USART_TypeDef* USARTx, uint16_t USART_FLAG)
{
FlagStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_FLAG(USART_FLAG));
/* The CTS flag is not available for UART4 and UART5 */
if (USART_FLAG == USART_FLAG_CTS)
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
if ((USARTx->SR & USART_FLAG) != (uint16_t)RESET)
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the USARTx's pending flags.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_FLAG: specifies the flag to clear.
* This parameter can be any combination of the following values:
* @arg USART_FLAG_CTS: CTS Change flag (not available for UART4 and UART5).
* @arg USART_FLAG_LBD: LIN Break detection flag.
* @arg USART_FLAG_TC: Transmission Complete flag.
* @arg USART_FLAG_RXNE: Receive data register not empty flag.
*
* @note
* - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun
* error) and IDLE (Idle line detected) flags are cleared by software
* sequence: a read operation to USART_SR register (USART_GetFlagStatus())
* followed by a read operation to USART_DR register (USART_ReceiveData()).
* - RXNE flag can be also cleared by a read to the USART_DR register
* (USART_ReceiveData()).
* - TC flag can be also cleared by software sequence: a read operation to
* USART_SR register (USART_GetFlagStatus()) followed by a write operation
* to USART_DR register (USART_SendData()).
* - TXE flag is cleared only by a write to the USART_DR register
* (USART_SendData()).
* @retval None
*/
void USART_ClearFlag(USART_TypeDef* USARTx, uint16_t USART_FLAG)
{
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CLEAR_FLAG(USART_FLAG));
/* The CTS flag is not available for UART4 and UART5 */
if ((USART_FLAG & USART_FLAG_CTS) == USART_FLAG_CTS)
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
USARTx->SR = (uint16_t)~USART_FLAG;
}
/**
* @brief Checks whether the specified USART interrupt has occurred or not.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_IT: specifies the USART interrupt source to check.
* This parameter can be one of the following values:
* @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5)
* @arg USART_IT_LBD: LIN Break detection interrupt
* @arg USART_IT_TXE: Tansmit Data Register empty interrupt
* @arg USART_IT_TC: Transmission complete interrupt
* @arg USART_IT_RXNE: Receive Data register not empty interrupt
* @arg USART_IT_IDLE: Idle line detection interrupt
* @arg USART_IT_ORE: OverRun Error interrupt
* @arg USART_IT_NE: Noise Error interrupt
* @arg USART_IT_FE: Framing Error interrupt
* @arg USART_IT_PE: Parity Error interrupt
* @retval The new state of USART_IT (SET or RESET).
*/
ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)
{
uint32_t bitpos = 0x00, itmask = 0x00, usartreg = 0x00;
ITStatus bitstatus = RESET;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_GET_IT(USART_IT));
/* The CTS interrupt is not available for UART4 and UART5 */
if (USART_IT == USART_IT_CTS)
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
/* Get the USART register index */
usartreg = (((uint8_t)USART_IT) >> 0x05);
/* Get the interrupt position */
itmask = USART_IT & IT_Mask;
itmask = (uint32_t)0x01 << itmask;
if (usartreg == 0x01) /* The IT is in CR1 register */
{
itmask &= USARTx->CR1;
}
else if (usartreg == 0x02) /* The IT is in CR2 register */
{
itmask &= USARTx->CR2;
}
else /* The IT is in CR3 register */
{
itmask &= USARTx->CR3;
}
bitpos = USART_IT >> 0x08;
bitpos = (uint32_t)0x01 << bitpos;
bitpos &= USARTx->SR;
if ((itmask != (uint16_t)RESET)&&(bitpos != (uint16_t)RESET))
{
bitstatus = SET;
}
else
{
bitstatus = RESET;
}
return bitstatus;
}
/**
* @brief Clears the USARTx's interrupt pending bits.
* @param USARTx: Select the USART or the UART peripheral.
* This parameter can be one of the following values:
* USART1, USART2, USART3, UART4 or UART5.
* @param USART_IT: specifies the interrupt pending bit to clear.
* This parameter can be one of the following values:
* @arg USART_IT_CTS: CTS change interrupt (not available for UART4 and UART5)
* @arg USART_IT_LBD: LIN Break detection interrupt
* @arg USART_IT_TC: Transmission complete interrupt.
* @arg USART_IT_RXNE: Receive Data register not empty interrupt.
*
* @note
* - PE (Parity error), FE (Framing error), NE (Noise error), ORE (OverRun
* error) and IDLE (Idle line detected) pending bits are cleared by
* software sequence: a read operation to USART_SR register
* (USART_GetITStatus()) followed by a read operation to USART_DR register
* (USART_ReceiveData()).
* - RXNE pending bit can be also cleared by a read to the USART_DR register
* (USART_ReceiveData()).
* - TC pending bit can be also cleared by software sequence: a read
* operation to USART_SR register (USART_GetITStatus()) followed by a write
* operation to USART_DR register (USART_SendData()).
* - TXE pending bit is cleared only by a write to the USART_DR register
* (USART_SendData()).
* @retval None
*/
void USART_ClearITPendingBit(USART_TypeDef* USARTx, uint16_t USART_IT)
{
uint16_t bitpos = 0x00, itmask = 0x00;
/* Check the parameters */
assert_param(IS_USART_ALL_PERIPH(USARTx));
assert_param(IS_USART_CLEAR_IT(USART_IT));
/* The CTS interrupt is not available for UART4 and UART5 */
if (USART_IT == USART_IT_CTS)
{
assert_param(IS_USART_123_PERIPH(USARTx));
}
bitpos = USART_IT >> 0x08;
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wconversion"
#endif
itmask = ((uint16_t)0x01 << (uint16_t)bitpos);
// [ILG]
#if defined ( __GNUC__ )
#pragma GCC diagnostic pop
#endif
USARTx->SR = (uint16_t)~itmask;
}
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
================================================
FILE: firmware/system/src/stm32f1-stdperiph/stm32f10x_wwdg.c
================================================
/**
******************************************************************************
* @file stm32f10x_wwdg.c
* @author MCD Application Team
* @version V3.5.0
* @date 11-March-2011
* @brief This file provides all the WWDG firmware functions.
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
*