User Tools

Site Tools


Writing /var/lib/dokuwiki/data/meta/teaching/ie0117/proyectos/2014/i/proyecto_1/dar_jose_rafael_arce_gamboa.meta failed
teaching:ie0117:proyectos:2014:i:proyecto_1:dar_jose_rafael_arce_gamboa

This is an old revision of the document!


To implement features of the STM32 F3 Discovery microcontroller

"To implement features of the STM32 F3 Discovery micro controller" : Project 2

Jose Rafael Arce Gamboa, B20493

Introduction

This project consists on using the code of the free software library libopencm3 to implement features of the STM32 F3 Discovery microcontroller. To do so, the code already provided in this library for other similar microcontroller was studied, as well as the data sheet and the reference manual of the corresponding devices. In this way, the main goal is to create new code for features that are not currently held for the F3 model on the library.

The STM32 F3 Micro-controller is a device that works with a 32-bit cortex ARM core, running at 72 MHz with a number of integrated peripherals and several applications like comparators, operational amplifiers, ADCs and DACs.

General Objective

To implement the features of the STM32 F3 Discovery micro controller using the libopencm3 library.

Specific Objectives

  1. To operate the development board STM32 F3 Discovery using the free software project libopencm3 and its examples.
  2. To identify the features of the STM32 F3 board that are currently held by libopecm3.
  3. From the features that are not yet supported, to make a list of priorities to implement.
  4. From the features that are not yet supported, to implement at least two of them.
  5. To update the documentation on the official wiki of the libopencm3 project.

Implementation

The libopencm3 project aims to create free and open firmware library for various microcontrollers, including ST STM32. Libopencm3. As it can be seen on the official wiki, there is not currently available documentation for the features held on the STM32 F3 Discovery series. To download and install the libopencm3, it is necessary to install the ARM Toolchain which is a crosscompiler tool for ARM cortex devices such as the STM32 F3, as well as the libftdil1 and openocd libraries to communicate with the chips libftdil1 openocd. A detailed guide to install libopencm3 and its examples can be found on the tutorial provided on the wiki of the Arcoslab Arm Toolchain.

Once you have the library installed, you will find the files and registers on a directory located in local. You can type the following.

 $cd ~/local/src/libopencm3-examples/
 

Where you will find two subdirectories, examples and libopencm3. On the examples subdirectory, you will find a number of programs that can be flashed to several kinds of micro controller. To find the ones that are written for the F3, you must type

 $cd ~/local/src/libopencm3-examples/examples/stm32/f3/stm32f3-discovery

Here, you will find a number of subdirectories, each one of them has a program that can be flashed to your unit, such as miniblink or fancyblink. If you want to run one of these programs, you must move to the correspondig subdirectory, then type:

 $make
 

Now, connect your micro-controller to your computer using an USB cable, and type:

 $make flash
 

You can easily check what is the function of each program by reading the README file, or by reading directly the source code of the program on the .c file. Each one of these examples programs make use of the libopencm3 features, which files are properly located on the libopencm3 subdirectory. Now, for each feature that is supported by libopencm3 there are two files. One of them, whose name ends with .h, has the registers and the definition of the functions associated a particular feature, and can be found in the following direction:

 $cd ~/local/src/libopencm3-examples/libopencm3/include/libopencm3
 

In order to find the files which are particularly associated with the F3, type

 $cd stm32/
 $cd f3/
 

Now, this direction contains all the features of the micro-controller that already have support on libopencm3. They are:

  1. adc: Analog-to-digital converters.
  2. crc: Cyclic redundancy check calculation unit.
  3. dac: Digital-to-analog converter.
  4. dma: Direct-memory-acces controller.
  5. gpio: General-purpose I/Os.
  6. i2c: Inter-integrated circuit.
  7. iwdg: Independent watchdog
  8. memorymap.h : A file that specifies the location of several definitions of other files in the memory.
  9. nvic: Nested vectored interrupt controller.
  10. pwr: Power controll.
  11. rcc: Reset and clock control.
  12. rtc: Real-time clock.
  13. spi: Serial peripheral interface.
  14. timer
  15. usart: Universal synchronous asynchronous receiver transmitter.

For a further inspection of the purpose of any of these features, you can check the STM32 F3 reference manual, available on F3 reference manual. Each one of these files, has the same general structure. First, it has a #ifndef statement, which checks if the given token was defined earlier, and if it is not so, it is followed bye a #define statement, which instructions extends to whole file, until the last #endif. First, it comes the Module definitios, which are used to distinguish a module from another. For example, if you check the reference amual you will find that the F3 has four ADCs, and so adc.h has four module definitios, each one of them identified by a number from 0 to 3. Then it comes the Register definitios. They are used to identify the place in memory of each module. In libopencm3, they are defined using a macro of the kinf MMIO32(), which returns a reference to the value of a space in memory. The parameter of this macro, is the base position, which was previously defined in memorymap.h, followed by a number in hexadecimal notation that specifies the particular position you want to know. Then it comes the Register values. Each feature has a set of properties which can have a number of different values. If you check the reference manual, for example in the case of the ADC, you will find a chart called the register map, which shows which bits are assigned to each property, and where they are found. Because each bit can have a value of cero or one, then a property defined by n bits can have up to 2^n different values. This part of the code uses a bitwise operators to identify each position, where the operator « stands for a left shift bitwise operators. In the case that a property is defined by more than one bit, it is used to define an specific shift, that later will be used to recognize the particular register. The code then is followed by the API definitions, which are not allways defined in the code, and finally it comes the definitions of the API functions, which usually are in charge of assign a particular value to a indiviudal or a set of bits, as well as read the value of particular bit.

The explicit definitios of these functions are found in the other kind of file, which are found in the lib directory by typing:

 $cd ~/local/src/libopencm3-examples/libopencm3/lib/stm32
 

To find the ones that are particular of the f3:

 $cd f3/

Here you will find a .c file for each .h found in the include subdirectory. These files give the instructions of each functions, and they also use bitwise operators. For this project, it was chosen to do the files for the features of the Comparator and the Operational Amplifier. For the first, the task was easier because there was already a file written for the STM32 F0 discovery. Checking the reference manual, it was found that the F3 has 7 comparators, and each one has a register of 32 bits. It is important to have in mind that the comparator is a device that receives two inputs, the inverting and the non inverting input, and produces an output, depending which one of the inputs is bigger. The main properties were OUT, which gives the value of the input, blanking, which prevents the current to trip, the hysteresis, which avoids spurious outputs in the case of noising signals, the output that can invert the polarity in the output, the outsel which defines which timer must be connected to the output, the inmsel which defines the inverting input selection from a list of predetermined inputs, the mode which adjusts the speed consumption, and EN, which defines whether the comparator is enabled or not. The register chart appears here.

And so, the code created is the following, for the .h and .c files:

 #ifndef LIBOPENCM3_COMP_H
 #define LIBOPENCM3_COMP_H
 /**@{*/
 /*****************************************************************************/
 /* Module definitions                                                        */
 /*****************************************************************************/
 #define COMP1	0
 #define COMP2	1
 #define COMP3	2
 #define COMP4	3
 #define COMP5	4
 #define COMP6	5
 #define COMP7	6
 /*****************************************************************************/
 /* Register definitions                                                      */
 /*****************************************************************************/
 #define COMP_CSR(i)			MMIO32(COMP_BASE + 0x1c + (i)*4)// Aqui tuve que cambiar por COMP_BASE
 #define COMP_CSR1			MMIO32(COMP_BASE + 0x1c)
 #define COMP_CSR2			MMIO32(COMP_BASE + 0x20)
 #define COMP_CSR3			MMIO32(COMP_BASE + 0x24)
 #define COMP_CSR4			MMIO32(COMP_BASE + 0x28) 
 #define COMP_CSR5			MMIO32(COMP_BASE + 0x2c)
 #define COMP_CSR6			MMIO32(COMP_BASE + 0x30)
 #define COMP_CSR7			MMIO32(COMP_BASE + 0x34)
 /*****************************************************************************/
 /* Register values                                                           */
 /*****************************************************************************/
 /* COMP_CSR Values ----------------------------------------------------------*/
 //En este caso, parece que todos son iguales
 #define COMP_CSR_LOCK			(1 << 31)
 #define COMP_CSR_OUT(i)			MMIO32((COMP_BASE + 0x1c + (i)*4) << 30)
 ///Aqui quiero definir un macro para el out de cada comparador en particular
 //se anade la primera funcion inmmsel, la cual esta habilitada solo para los comparadores 2, 4 y 6
 #define COMP_CSR_COMP1INMSEL                (1 << 22)
 //Anadir la region de Blanking, que abarca del registro 18 al 20 para todos los comparadores
 /#define COMP_RES_1_SHIFT                21  
 #define COMP_CSR_BLANKING_SHIFT         18
 #define COMP_CSR_BLANKING               (7 << COMP_CSR_BLANKING_SHIFT) //8 opciones, pero para 1,2,3 y 4 solo hay 4 ocpiones,y para 5 opciones para 6 y 7, 
 #define COMP_CSR_BLANKING_OPT1          (0 << COMP_CSR_BLANKING_SHIFT) /// en realidad no importa como se llamen
 #define COMP_CSR_BLANKING_OPT2          (1 << COMP_CSR_BLANKING_SHIFT)
 #define COMP_CSR_BLANKING_OPT3          (2 << COMP_CSR_BLANKING_SHIFT)
 #define COMP_CSR_BLANKING_OPT4          (3 << COMP_CSR_BLANKING_SHIFT)
 #define COMP_CSR_BLANKING_OPT5          (4 << COMP_CSR_BLANKING_SHIFT)
 #define COMP_CSR_BLANKING_OPT6          (5 << COMP_CSR_BLANKING_SHIFT)
 #define COMP_CSR_BLANKING_OPT7          (6 << COMP_CSR_BLANKING_SHIFT)
 #define COMP_CSR_BLANKING_OPT8          (7 << COMP_CSR_BLANKING_SHIFT)
 ///La de histeresis, en registro 16 y 17 solo la tienen 1,3 5, y 7
 #define COMP_CSR_HYST_SHIFT		16
 #define COMP_CSR_HYST			(3 << COMP_CSR_HYST_SHIFT)//4ocpiones estan definidas iguales para todos
 #define COMP_CSR_HYST_NO		(0 << COMP_CSR_HYST_SHIFT)
 #define COMP_CSR1_HYST_LOW		(1 << COMP_CSR_HYST_SHIFT)
 #define COMP_CSR1_HYST_MED		(2 << COMP_CSR_HYST_SHIFT)
 #define COMP_CSR1_HYST_HIGH		(3 << COMP_CSR_HYST_SHIFT)
 ///Pol es una que la tienen todos
 #define COMP_CSR_POL			(1 << 15)
 //#define COMP_RES_2_SHIFT                14  
 ///Outsel la tienen todos del registro 10 al 13 tiene 16 opciones, pero definidas diferentes para todos,las ultimas vienen desocupadas
 #define COMP_CSR_OUTSEL_SHIFT	        	10
 #define COMP_CSR_OUTSEL		        	(15 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT1		        (0 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT2	                (1 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT3	                (2 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT4	                (3 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT5	                (4 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT6	                (5 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT7	                (6 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT8	                (7 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT9	                (8 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT10	                (9 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT11	                (10 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT12	                (11 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT13	                (12 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT14	                (13 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT15	                (14 << COMP_CSR_OUTSEL_SHIFT)
 #define COMP_CSR_OUTSEL_OPT16	                (15 << COMP_CSR_OUTSEL_SHIFT)
 //WINMODE, HABILITADO SOLO PARA 2, 4 Y 6 window mode
 #define COMP_CSR_WINMODE                       (1 << 9)
 ///Ahora el insel
 #define COMP_CSR_INSEL                         (1 << 7)
 //AHORA SIGUE INMSEL, DEFINIDO PARA TODOS, SEGUN LA GUIA DEL MICROCONTROLADOR del registro 4 al 6, tiene 8 opciones aunque algunas tienen mas?
 #define COMP_CSR_INMSEL_SHIFT		4
 #define COMP_CSR_INMSEL	         	(7 << COMP_CSR_INMSEL_SHIFT)
 #define COMP_CSR_INMSEL_OPT1    	        (0 << COMP_CSR_INMSEL_SHIFT)
 #define COMP_CSR_INMSEL_OPT2    	        (1 << COMP_CSR_INMSEL_SHIFT)
 #define COMP_CSR_INMSEL_OPT3    	        (2 << COMP_CSR_INMSEL_SHIFT)
 #define COMP_CSR_INMSEL_OPT4                 (3 << COMP_CSR_INMSEL_SHIFT)
 #define COMP_CSR_INMSEL_OPT5    	        (4 << COMP_CSR_INMSEL_SHIFT)
 #define COMP_CSR_INMSEL_OPT6      	        (5 << COMP_CSR_INMSEL_SHIFT)
 #define COMP_CSR_INMSEL_OPT7		        (6 << COMP_CSR_INMSEL_SHIFT)
 #define COMP_CSR_INMSEL_OPT8		        (7 << COMP_CSR_INMSEL_SHIFT)
 //PROBABLEMENTE SHIFT SEA LO MISMO QUE MODE, COMPRUEBE ESO DESPUES todos tienen speed
 //DEFINIDO DEL REGISTRO 2 AL 3, HAY 4 OPCIONES DEFINIDAS IGUALES PARA TODOS
 #define COMP_CSR_SPEED_SHIFT		         2
 #define COMP_CSR_SPEED			(3 << COMP_CSR_SPEED_SHIFT)
 #define COMP_CSR_SPEED_HIGH		        (0 << COMP_CSR_SPEED_SHIFT)
 #define COMP_CSR_SPEED_MED		        (1 << COMP_CSR_SPEED_SHIFT)
 #define COMP_CSR_SPEED_LOW		        (2 << COMP_CSR_SPEED_SHIFT)
 #define COMP_CSR_SPEED_VERYLOW		(3 << COMP_CSR_SPEED_SHIFT)
 //solo para el comparador 1 TIENE EL INP_DAC
 #define COMP_CSR_INP_DAC			(1 << 1)
 //para los 7 comparadores
 #define COMP_CSR_EN			        (1 << 0)
 /*****************************************************************************/
 /* API definitions                                                           */
 /*****************************************************************************/
 /*****************************************************************************/
 /* API Functions                                                             */
 /*****************************************************************************/
 BEGIN_DECLS
 //MODIFICANDO LAS FUNCIONES SEGUN LOS PARAMETROS DEL F3, PROBABLEMENTE HAYA QUE DEFINIR UNA PARA CADA COMPARADOR DEL MICROCONTROLADOR
 void comp_enable(uint8_t id);
 void comp_disable(uint8_t id);
 void comp_select_blanking(uint8_t id, uint32_t blanking); //Tuve que anadir la del blanking
 void comp_select_inverting_input(uint8_t id, uint32_t inverting_input);//AQUI SE USA INSEL inverting input selection
 void comp_select_non_inverting_0(uint8_t id);
 void comp_select_non_inverting_1(uint8_t id);
 void comp_select_output(uint8_t id, uint32_t output);//AQUI SE USA OUTSEL
 void comp_select_hyst(uint8_t id,uint32_t hyst);//HISTERESIS
 void comp_select_speed(uint8_t id, uint32_t speed);//MODE O SPEED
 uint32_t comp_read_output(uint8_t id); //devuelve 1 o 0, segun cual haya sido la respuesta
 int returnbit(uint32_t byteFlag, int whichbit);
 END_DECLS
 /**@}*/
 #endif
 #include <libopencm3/stm32/comparator.h>
 void comp_enable(uint8_t id)
 {
         COMP_CSR(id) |= COMP_CSR_EN; 
 }
 void comp_disable(uint8_t id)
 {
 	   COMP_CSR(id) &= ~COMP_CSR_EN;
 }
 void comp_select_blanking(uint8_t id, uint32_t blanking)
 {
        COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_BLANKING ) | blanking; ///En analogia de las demas funciones
 }
 void comp_select_inverting_input(uint8_t id, uint32_t inverting_input)
 {
   COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_INMSEL) | inverting_input;
 }
 void comp_select_non_inverting_0(uint8_t id)
 {
   COMP_CSR(id) &= ~COMP_CSR_INSEL;
 }
 void comp_select_non_inverting_1(uint8_t id) 
 {
         COMP_CSR(id) |= COMP_CSR_INSEL;
 }
 void comp_select_output(uint8_t id, uint32_t output)
 { 
   COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_OUTSEL) | output;
 }
 void comp_select_hyst(uint8_t id, uint32_t hyst)
 {
   COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_HYST) | hyst;
 }
 void comp_select_speed(uint8_t id, uint32_t speed)
 {
   COMP_CSR(id) = (COMP_CSR(id) & ~COMP_CSR_SPEED) | speed;
 }
   uint32_t comp_read_output(uint8_t id)
 {
   return COMP_CSR(id);
 }
 int returnbit(uint32_t byteFlag, int whichBit)
 {
     if (whichBit > 0 && whichBit <= 32)
         return (byteFlag & (1<<(whichBit-1)));
     else
         return 0;
 }
 /**@}*/

For the operational amplifier it was done a similar work. On the F3, there are for opamps, and the properties are the outcal, which gives a flag if the opamp is used as a comparator, the TSTREF used to output the internal reference voltage, the PGA_GAIN, to set the gain of the opamp, the calsel, to set the calibration, the calon to enable the calibration, the VPS_SEL to chose the non inverting input secondary selection, VMS_SEL for the inverting input secondary selection, the TMC_EN for enable the controlled Mux mode, VM_SEL for the inverrting input selection, VP_SEL for the non inverting input selection, and OPAMPEN, to enable the opamp. The opamp register map, as well as the .h and .c files written are the following.

 #ifndef LIBOPENCM3_OPAMP_H
 #define LIBOPENCM3_OPAMP_H
 ///El F3 tiene 4 amplificadores operacionales, voy a definirlos
 /*****************************************************************************/
 /* Module definitions                                                        */
 /*****************************************************************************/
 #define OPAMP1   0
 #define OPAMP2   1
 #define OPAMP3   2
 #define OPAMP4   3
 //////Ahora el control de los registros
 /*****************************************************************************/
 /* Register definitions                                                      */
 /*****************************************************************************/
 //Note que para el OPAMP tambien se usa sl CSR control status register
 #define OPAMP_CSR(i)                    MMIO32(OPAMP_BASE + 0x38 + (i)*4) //OX44??          
 #define OPAMP_CSR1	                OPAMP_CSR(OPAMP1)		
 #define OPAMP_CSR2	                OPAMP_CSR(OPAMP2)	
 #define OPAMP_CSR3			OPAMP_CSR(OPAMP3)
 #define OPAMP_CSR4			OPAMP_CSR(OPAMP4)
 /*****************************************************************************/
 /* Register values                                                           */
 /*****************************************************************************/
 /* OPAMP_CSR Values ----------------------------------------------------------*/
 //Estos son iguales para los 4 opamps
 #define OPAMP_CSR_LOCK                  (1 << 31)
 #define OPAMP_CSR_OUTCAL(i)             MMIO32((OPAMP_BASE + 0x38 + (i)*4) << 30)  
 #define OPAMP_CSR_TSTREF                (1 << 29)  //INTERNAL REFERENCE VOLTAGE
 #define OPAMP_CSR_TRIMOFFSETIN_SHIFT    24         //Offset trimming value, no especifica casos
 #define OPAMP_CSR_TRIMOFFSETP_SHIFT     19         //Offset trimming value, no especifica casos
 #define OPAMP_CSR_USER_TRIM             (1 << 18)   //USER TRIMMING ENABLE definido para todos
 //PGA Gain, definido de el registro 14 al 17, son 16 opciones, definidas igual para todas
 #define OPAMP_CSR_PGA_GAIN_SHIFT        14 //GAIN IN PGA MODE
 #define OPAMP_CSR_PGA_GAIN              (15 << OPAMP_CSR_PGA_GAIN_SHIFT) //16 CASOS
 #define OPAMP_CSR_PGA_GAIN_NIG2         (0 << OPAMP_CSR_PGA_GAIN_SHIFT)//NON INVERTING GAIN 2
 #define OPAMP_CSR_PGA_GAIN_NIG4         (1 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_NIG8         (2 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_NIG16        (3 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_NIG2_VM0     (4 << OPAMP_CSR_PGA_GAIN_SHIFT)//CONECTED TO VM0
 #define OPAMP_CSR_PGA_GAIN_NIG4_VM0     (5 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_NIG8_VM0     (6 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_NIG16_VM0    (7 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_NIG2_VM1     (8 << OPAMP_CSR_PGA_GAIN_SHIFT)//CONECTED TO VM1
 #define OPAMP_CSR_PGA_GAIN_NIG4_VM1     (9 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_NIG8_VM1     (10 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_NIG16_VM1    (11 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_OPT13        (12 << OPAMP_CSR_PGA_GAIN_SHIFT) //opciones definidas de mas
 #define OPAMP_CSR_PGA_GAIN_OPT14        (13 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_OPT15        (14 << OPAMP_CSR_PGA_GAIN_SHIFT)
 #define OPAMP_CSR_PGA_GAIN_OPT16        (15 << OPAMP_CSR_PGA_GAIN_SHIFT)
 ///calsel definido para 12 y 13 definido igual para todos
 #define OPAMP_CSR_CALSEL_SHIFT          12   //CALIBRATION SELECTION
 #define OPAMP_CSR_CALSEL                (3 << OPAMP_CSR_CALSEL_SHIFT) //4 CASOS
 #define OPAMP_CSR_CALSEL_3              (0 << OPAMP_CSR_CALSEL_SHIFT)
 #define OPAMP_CSR_CALSEL_10             (1 << OPAMP_CSR_CALSEL_SHIFT)
 #define OPAMP_CSR_CALSEL_50             (2 << OPAMP_CSR_CALSEL_SHIFT)
 #define OPAMP_CSR_CALSEL_90             (3 << OPAMP_CSR_CALSEL_SHIFT)
 //El calon en el registro 11
 #define OPAMP_CSR_CALON                 (1 << 11) // CALIBRATION MODE ENABLE
 ///VPS_SEL definido en 9 y 10 para todos
 #define OPAMP_CSR_VPS_SEL_SHIFT         9 //NON INVERTING INPUT SECONDARY SELECTION
 #define OPAMP_CSR_VPS_SEL               (3 << OPAMP_CSR_VPS_SEL_SHIFT) //4 casos
 #define OPAMP_CSR_VPS_SEL_OPT1          (0 << OPAMP_CSR_VPS_SEL_SHIFT)
 #define OPAMP_CSR_VPS_SEL_OPT2          (1 << OPAMP_CSR_VPS_SEL_SHIFT)
 #define OPAMP_CSR_VPS_SEL_OPT3          (2 << OPAMP_CSR_VPS_SEL_SHIFT)
 #define OPAMP_CSR_VPS_SEL_OPT4          (3 << OPAMP_CSR_VPS_SEL_SHIFT)
 //EN REGISTRO 8
 #define OPAMP_CSR_VMS_SEL               (1 << 8) // INVERTING INPUT SECONDARY SELECTION
 //EN REGISTRO 7
 #define OPAMP_CSR_TCM_EN                (1 << 7) //TIMER CONTROLLER MUX MODE ENABLE
 //EN REGISTROS 5 Y 6
 #define OPAMP_CSR_VM_SEL_SHIFT          5 //INVERTING INPUT SELECTION
 #define OPAMP_CSR_VM_SEL                (3 << OPAMP_CSR_VM_SEL_SHIFT)//4 casos
 #define OPAMP_CSR_VM_SEL_OPT1           (0 << OPAMP_CSR_VM_SEL_SHIFT)
 #define OPAMP_CSR_VM_SEL_OPT2           (1 << OPAMP_CSR_VM_SEL_SHIFT)
 #define OPAMP_CSR_VM_SEL_OPT3           (2 << OPAMP_CSR_VM_SEL_SHIFT)
 #define OPAMP_CSR_VM_SEL_OPT4           (3 << OPAMP_CSR_VM_SEL_SHIFT)
 //BIT 4 RESERVADO
 //REGISTROS 2 Y 3 DEFINIDOS DISTINTO PARA CADA UNO
 #define OPAMP_CSR_VP_SEL_SHIFT           2 //  NON INVERTING INPUT SELECTION
 #define OPAMP_CSR_VP_SEL                 (3 << OPAMP_CSR_VP_SEL_SHIFT) //4 casos
 #define OPAMP_CSR_VP_SEL_OPT1            (0 << OPAMP_CSR_VP_SEL_SHIFT)
 #define OPAMP_CSR_VP_SEL_OPT2            (1 << OPAMP_CSR_VP_SEL_SHIFT)
 #define OPAMP_CSR_VP_SEL_OPT3            (2 << OPAMP_CSR_VP_SEL_SHIFT)
 #define OPAMP_CSR_VP_SEL_OPT4            (3 << OPAMP_CSR_VP_SEL_SHIFT)
 #define OPAMP_CSR_FORCE_VP               (1 << 1) //SIN DESCRIPCION
 #define OPAMP_CSR_OPAMPEN                (1 << 0) //ENABLE
 /*****************************************************************************/
 /* API definitions                                                           */
 /*****************************************************************************/
 /*****************************************************************************/
 /* API Functions                                                             */
 /*****************************************************************************/
 BEGIN_DECLS
 void opamp_enable(uint8_t id);
 void opamp_disable(uint8_t id);
 void opamp_enable_user_trim(uint8_t id);
 void opamp_disable_user_trim(uint8_t id);
 void opamp_select_pga_gain(uint8_t id, uint32_t pga_gain);
 void opamp_select_calsel(uint8_t id, uint32_t calsel);
 void opamp_enable_calon(uint8_t id);
 void opamp_disable_calon(uint8_t id);
 void opamp_select_vps_sel(uint8_t id, uint32_t vps_sel);
 void opamp_select_vm_sel(uint8_t id, uint32_t vm_sel);
 void opamp_select_vp_sel(uint8_t id, uint32_t vp_sel);
 uint32_t opamp_read_register(uint8_t id);
 int returnbit(uint32_t byteFlag, int whichBit);
 END_DECLS
 /**@}*/
 #endif
 #include <libopencm3/stm32/opamp.h>
 void opamp_enable(uint8_t id)
 {
         OPAMP_CSR(id) |= OPAMP_CSR_OPAMPEN;
 }
 void opamp_disable(uint8_t id)
 {
   OPAMP_CSR(id) &= ~OPAMP_CSR_OPAMPEN;
 }
 void opamp_enable_user_trim(uint8_t id)
 {
         OPAMP_CSR(id) |= OPAMP_CSR_USER_TRIM;
 }
 void opamp_disable_user_trim(uint8_t id)
 }
   OPAMP_CSR(id) &= ~OPAMP_CSR_USER_TRIM;
 }
 void opamp_select_pga_gain(uint8_t id, uint32_t pga_gain)
 {
        OPAMP_CSR(id) = (OPAMP_CSR(id) & ~OPAMP_CSR_PGA_GAIN ) | pga_gain; ///En analogia de las demas funciones
 }
 void opamp_select_calsel(uint8_t id, uint32_t calsel) 
 {
 	   OPAMP_CSR(id) = (OPAMP_CSR(id) & ~OPAMP_CSR_CALSEL) | calsel;
 }
 void opamp_enable_calon(uint8_t id)
 {
         OPAMP_CSR(id) |= OPAMP_CSR_CALON;
 }
 void opamp_disable_calon(uint8_t id)
 {
   OPAMP_CSR(id) &= ~OPAMP_CSR_CALON;
 }
 void opamp_select_vps_sel(uint8_t id, uint32_t vps_sel)
 {
   OPAMP_CSR(id) = (OPAMP_CSR(id) & ~OPAMP_CSR_VPS_SEL) | vps_sel;
 }
 void opamp_select_vm_sel(uint8_t id, uint32_t vm_sel)
 {
         OPAMP_CSR(id) = (OPAMP_CSR(id) & ~OPAMP_CSR_VM_SEL) | vm_sel;
 }
 void opamp_select_vp_sel(uint8_t id, uint32_t vp_sel)
 {
   OPAMP_CSR(id) = (OPAMP_CSR(id) & ~OPAMP_CSR_VP_SEL) | vp_sel;
 }
    uint32_t opamp_read_register(uint8_t id)
 {
    return OPAMP_CSR(id);
 }
 int returnbit(uint32_t byteFlag, int whichBit)
 {
     if (whichBit > 0 && whichBit <= 32)
         return (byteFlag & (1<<(whichBit-1)));
     else
         return 0;
 }
 /**@}*/

In order to make this files work, you need to go to the following directory:

 $cd ~/local/src/libopencm3-examples/libopencm3/include/libopencm3/stm32
 

and add the following to file named comparator.h

#elif defined(STM32F3)

 #       include <libopencm3/stm32/f3/comparator.h>

Then, on the same direction, you must create another file named opamp.h similar the latter comparator.h file you just have edited. Finally, in order to compile the files you must go to this direction:

 $cd ~/local/src/libopencm3-examples/libopencm3/lib/stm32/f3
 

And edit the file Makefile. You must add comparator.o and opamp.o to the list of objects, leave the file, and then run the make command. You should not receive any error.

Results

The files compiled successfully. The board was micro controller was connected to a proto board with some variable resistors to test the adc.c program example, which ran successful. An attempt was made to write down a new program to test the new comp functions, however this was not yet possible. It is still necessary to add this new functions to the official wiki site, and declare the comp and opamp with register definitions,and convenience functions.

Conclusions

  1. The code created succesfully compiled.
  2. It is still necessary to run new tests on the board.
  3. It is still necessary to contact the managers of libopencm3 to add the new code created and then, edit their wiki page.

References

teaching/ie0117/proyectos/2014/i/proyecto_1/dar_jose_rafael_arce_gamboa.1457364283.txt.gz · Last modified: 2022/09/20 00:08 (external edit)