Why are my DFSDM register bits not changing on my STM32L476? - c

I am facing a problem with the DFSDM (Digital Filter for Sigma-Delta Modulation) of my STM32L476RE. Indeed, despite the fact that I have enabled the clock for the DFSDM, all the registers related to the my filter (in the code below: DFSDM1_Filter1->...) never change when I set a bit, whereas the registers related to my channel DFSDM1_Channel1->... do change well. As setting the clock is usuallythe solution for this kind of problem, I am stuck because, as I said, my clock is already enabled for DFSDM. Can anyone help? Thanks in advance!
// Enable DFSDM clock
RCC->CCIPR &= ~RCC_CCIPR_DFSDM1SEL; // Choose PCLK2 as clock
RCC->APB2ENR |= RCC_APB2ENR_DFSDM1EN; // Enable DFSDM clock
// Make sure DFSDM is disabled
DFSDM1_Channel0->CHCFGR1 &= ~DFSDM_CHCFGR1_DFSDMEN;
// Channel 1
DFSDM1_Channel1->CHCFGR1 &= ~DFSDM_CHCFGR1_CHINSEL; // Select own input (DATIN1)
DFSDM1_Channel1->CHCFGR1 &= ~DFSDM_CHCFGR1_DATMPX; // Data is taken from DATIN1 as 1 bit values
DFSDM1_Channel1->CHCFGR1 |= (0x01 <<2U); // Use internal clock for SPI format
DFSDM1_Channel1->CHCFGR1 |= (0x00 <<0U); // Strobe data on rising edge
DFSDM1_Channel1->CHCFGR1 |= DFSDM_CHCFGR1_CHEN; // Enable channel 1
// Filter 1 -> Channel 1, continuous regular conversion
DFSDM1_Filter1->FLTCR1 |= (0x01 <<24U); // Regular channel 1
DFSDM1_Filter1->FLTCR1 |= DFSDM_FLTCR1_FAST; // Fast mode enabled
DFSDM1_Filter1->FLTCR1 |= DFSDM_FLTCR1_RCONT; // Continuous mode
DFSDM1_Filter1->FLTCR1 |= DFSDM_FLTCR1_RDMAEN; // Enable DMA requests on regular conversion
DFSDM1_Filter1->FLTFCR |= ( 0x02 <<29U); // Select Sinc2 filter mode
DFSDM1_Filter1->FLTFCR |= ((1023) <<16U); // with FOSR = 1024
DFSDM1_Filter1->FLTFCR |= ((255) <<00U); // with IOSR = 256
DFSDM1_Filter1->FLTCR1 |= DFSDM_FLTCR1_DFEN; // Enable filter
// Global enable for DFSDM interface
DFSDM1_Channel0->CHCFGR1 |= DFSDM_CHCFGR1_DFSDMEN;
// Start conversion
DFSDM_Filter1->FLTCR1 |= DFSDM_FLTCR1_RSWSTART;

Related

STM32L011K4 with DMA RX using I2C data not appearing in buffer

I am trying to query a temperature sensor (TMP007) over an I2C bus using the L011K4's DMA controller. I've managed to get TMP007 to respond with good data, but that data isn't appearing in the buffer array that I pass my I2C DMA receive function.
What I expect to happen is that the I2C hardware is set up by the software in the Init and Read function, then the start condition is generated, the slave's address and register address are sent, then a second start/a restart is sent out followed by the slave's address again, and finally ending with a transmission of two bytes from TMP007 and a stop condition.
The data acquired from the temperature sensor should be appearing in a buffer that is passed into Start_Read (as MemoryBaseAddress), but that data does not appear when viewing the processor in debug mode after the read function has been called.
The Channel 3 transfer complete interrupt is being called, so I know the DMA has activated and managed the RX transfer, but the data doesn't appear in the desired buffer.
Here's an image of the communication being observed by a logic analyzer: https://i.imgur.com/SzySsXl.png
DIO2 is connected to the onboard LED, which tells us that the DMA transfer has completed (it's the only ISR with the LED toggle).
Any help would be greatly appreciated!
STM32L011K4 Datasheet: https://www.st.com/content/ccc/resource/technical/document/datasheet/42/c0/ab/e5/71/7a/47/0b/DM00206508.pdf/files/DM00206508.pdf/jcr:content/translations/en.DM00206508.pdf
STM32L011K4 Reference Manual: https://www.st.com/resource/en/reference_manual/dm00108282-ultralowpower-stm32l0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
void I2C1_DMA_Start_Read(int SlaveAddress, int RegisterAddress, int* MemoryBaseAddress, int BufferSize) {
I2C1->CR1 &= ~I2C_CR1_PE; // Disable I2C1
DMA1_Channel3->CCR &= ~DMA_CCR_EN; // Disable Channel 3 DMA
DMA1_Channel3->CCR &= ~(0x00007FFF); // Channel 3 DMA mask
// Configure DMA Channel 3 for 16 bit memory and peripheral, and other aliased settings (reference manual page 249, 10.4.3)
DMA1_Channel3->CCR |= (0b11 << 12)|(0b01 << 10)|(0b01 << 8)|DMA_CCR_MINC|DMA_CCR_TEIE|DMA_CCR_TCIE;
DMA1_Channel3->CPAR = (uint32_t) &(I2C1->RXDR);
DMA1_Channel3->CMAR = (uint32_t) MemoryBaseAddress;
DMA1_Channel3->CNDTR = (uint16_t) BufferSize;
DMA1_Channel3->CCR |= DMA_CCR_EN; // Activate DMA channel 3
I2C1->CR1 |= I2C_CR1_NACKIE; // Enable no acknowledge interrupt for I2C1
I2C1->CR2 |= ((uint8_t) (SlaveAddress << 1)); // Set up the slave address
I2C1->CR2 &= ~I2C_CR2_RD_WRN; // Master requests a write transfer in order to send the register
I2C1->CR1 |= I2C_CR1_PE|I2C_CR1_RXDMAEN; // Enable I2C1 and RX DMA for I2C1
I2C1->CR2 &= ~(0xFF << I2C_CR2_NBYTES_Pos); // Mask byte count
I2C1->CR2 |= (0x01 << I2C_CR2_NBYTES_Pos); // Transfer one byte (the slave's register address)
while(!(I2C1->ISR & I2C_ISR_TXE)); // Wait until TX data register is empty
I2C1->TXDR = RegisterAddress; // Set the transmit data to the desired register address
I2C1->CR2 |= I2C_CR2_START; // Generate start condition
while(I2C1->CR2 & I2C_CR2_START); // Wait until hardware clears the start bit
while(!(I2C1->ISR & I2C_ISR_TC)); // Wait until hardware clears the transmit complete bit
I2C1->CR2 |= I2C_CR2_RD_WRN; // Master requests a read transfer after sending over the register address
I2C1->CR2 &= ~(0xFF << I2C_CR2_NBYTES_Pos); // Mask byte count
I2C1->CR2 |= (0x02 << I2C_CR2_NBYTES_Pos); // Master looks for two bytes from the slave
I2C1->CR2 |= I2C_CR2_START; // Generate start condition
while(I2C1->CR2 & I2C_CR2_START); // Wait until hardware clears the start bit
return;
}
void DMA1_Channel2_3_IRQHandler() {
if(DMA1->ISR & DMA_ISR_TCIF3) {
GPIOB->ODR ^= 1 << 3; // Toggle the onboard LED as an indicator
I2C1->CR2 |= I2C_CR2_STOP; // Generate stop condition
while(I2C1->CR2 & I2C_CR2_STOP); // Wait until hardware clears the stop bit
DMA1->IFCR |= DMA_IFCR_CTCIF3; // Clear transfer complete interrupt bit
I2C1->CR1 &= ~I2C_CR1_PE; // Disable I2C1
DMA1_Channel3->CCR &= ~DMA_CCR_EN; // Disable Channel 3 DMA
} else if(DMA1->ISR & DMA_ISR_TEIF3) {
I2C1->CR2 |= I2C_CR2_STOP; // Generate stop condition (if I2C comm is already stopped on error, delete this and following line)
while(I2C1->CR2 & I2C_CR2_STOP); // Wait until hardware clears the stop bit
DMA1->IFCR |= DMA_IFCR_CTEIF3; // Clear transfer error interrupt bit
I2C1->CR1 &= ~I2C_CR1_PE; // Disable I2C1
DMA1_Channel3->CCR &= ~DMA_CCR_EN; // Disable Channel 3 DMA
}
return;
}
void I2C1_IRQHandler() {
if(I2C1->ISR & I2C_ISR_NACKF) {
//GPIOB->ODR ^= 1 << 3; // Toggle the onboard LED as an indicator
I2C1->ICR |= I2C_ICR_NACKCF;
}
return;
}

STM32L011K4 with DMA using I2C Start Condition not Occurring

I'm attempting to use the STM32L011K4's DMA controller to communicate with slave devices over I2C. Currently, I have no slave devices and am just trying to get the microcontroller to send the start condition out onto the I2C bus, but that is not happening.
When I run this code in debugging mode through the STM32CubeIDE, I notice that the start bit is set, but it never clears even though the reference manual says it should be cleared by hardware once the start condition occurs (page 656 for I2C_CR2).
Monitoring the SDA and SCL lines on my oscilloscope also show that they are a logical 1. Note: I'm using the NUCLEO-L011K4 on a breadboard, so the IO pins are tied to Vref through 1k resistors. All configuration registers appear to contain the desired value when the code is stuck sending the start condition, so I don't believe they are getting clobbered by a random line of code.
I'm not sure what's preventing the start condition from being sent, so any help would be greatly appreciated.
STM32L011K4 Datasheet:
https://www.st.com/content/ccc/resource/technical/document/datasheet/42/c0/ab/e5/71/7a/47/0b/DM00206508.pdf/files/DM00206508.pdf/jcr:content/translations/en.DM00206508.pdf
STM32L011K4 Reference Manual: https://www.st.com/resource/en/reference_manual/dm00108282-ultralowpower-stm32l0x1-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
Initialization code:
void Init_I2C1_DMA() {
/* Basic I2C Initialization for 100 kHz I2C, 24 MHz SYSCLK, /1 APB1 scaler */
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // Enable peripheral clock for I2C1
I2C1->CR1 &= ~(I2C_CR1_PE); // Disable I2C1
I2C1->CR1 = 0; // Reset CR1
I2C1->TIMINGR = 0; // Reset timer settings
/* APB1 clock (I2C1 clock) is set in RCC_CFGR reg -- keep at divide by 1 -- 24 MHz SYSCLK
* Refer to table 103 for timing value source. t_presc was found to be 250 ns for 100 kHz I2C, so PRESC was set to match that for SYSCLK = 24 MHz
* All subsequent settings are copied from table 103 from STM32L011K4 reference manual
*/
I2C1->TIMINGR |= (0x5 << 28)|(0x4 << 20)|(0x2 << 16)|(0x0F << 8)|(0x13 << 0);
/* Desired settings:
* RXDMAEN enable, ANF enable.
*/
I2C1->CR1 |= (0x8 << I2C_CR1_DNF_Pos)|I2C_CR1_ERRIE;
I2C1->CR2 = 0; // Reset contents (ACKs are enabled by default)
NVIC_EnableIRQ(I2C1_IRQn);
NVIC_SetPriority(I2C1_IRQn, 0);
/* DMA initialization */
/* Since this is peripheral to memory, we use I2C1_RX, which is available on DMA channels 3,7. We used channel 3, but 7 would work the same. */
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // Enable peripheral clock for DMA1
DMA1_Channel3->CCR &= ~(0x00000001); // Disable Channel 3 DMA
// Configure DMA channel mapping
DMA1_CSELR->CSELR &= ~0x00000F00; // Channel 3 re-mapping mask
DMA1_CSELR->CSELR |= 0x00000600; // Channel 3 re-mapped to I2C1_RX
/* Configure NVIC for DMA */
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0);
return;
}
void I2C1_DMA_Start_Read(uint8_t SlaveAddress, uint8_t RegisterAddress, int* MemoryBaseAddress, int BufferSize) {
// We need to put the device address out on the serial line before we can hand it over to the DMA
I2C1->CR1 &= ~(I2C_CR1_PE); // Disable I2C1
DMA1_Channel3->CCR &= ~DMA_CCR_EN; // Disable Channel 3 DMA
DMA1_Channel3->CCR &= ~(0x00007FFF); // Channel 3 DMA mask
// Configure DMA Channel 3 for 16 bit memory and peripheral, and other aliased settings (reference manual page 249, 10.4.3)
DMA1_Channel3->CCR |= (0b01 << 10)|(0b01 << 8)|DMA_CCR_MINC|DMA_CCR_TEIE|DMA_CCR_TCIE;
DMA1_Channel3->CPAR = (uint32_t) RegisterAddress;
DMA1_Channel3->CMAR = (uint32_t) MemoryBaseAddress;
DMA1_Channel3->CNDTR = (uint16_t) BufferSize;
I2C1->CR1 &= (~I2C_CR1_TXDMAEN); // Disable TX DMA for I2C1
I2C1->CR1 |= I2C_CR1_RXDMAEN; // Enable RX DMA for I2C1
// I2C1->CR2 |= ((uint8_t) (SlaveAddress << 1)); // Set up the slave address for DMA read
while(!(I2C1->ISR & I2C_ISR_TXE));
I2C1->TXDR |= ((uint8_t) (SlaveAddress << 1)); // Set up the slave address for DMA read
I2C1->CR2 |= I2C_CR2_RD_WRN;
DMA1_Channel3->CCR |= DMA_CCR_EN; // Activate DMA channel 3
I2C1->CR1 |= I2C_CR1_PE; // Enable I2C1
I2C1->CR2 |= I2C_CR2_START; // Generate start condition
while(I2C1->CR2 & I2C_CR2_START); // Wait until hardware clears the start bit
// ???
return;
}
According with reference manual(p. 604)
you need uncomment I2C1->CR2 |= ((uint8_t) (SlaveAddress << 1)); and comment I2C1->TXDR |= ((uint8_t) (SlaveAddress << 1)); for set slave address, and you need set the number of bytes to be transferred.
I can't see your initialisation of GPIO. Check is GPIO settings right (Alternative function and open-drain mode).
Also in reference manual written this
PE must be kept low during at least 3 APB clock cycles in order to perform the software
reset. This is ensured by writing the following software sequence: - Write PE=0 - Check
PE=0 - Write PE=1.
I think you should try to do so.
Also I advise using 4.7k resistor for pulling to VDD.

Stm32f4 counting pulses (How can I adjust the rising edge voltage ?)

At the moment I use TIM2 on the stm32f4 - Discovery Board to count pulses (rising edges). How can I adjust the thresholds for the rising edges ? I want to count 1 V pulses. At the moment it is just possible to count 2V pulses. I'm not able to find something about this in the documentation.
Here is the code of my timer function.
void timer_2_pulse_counter_gpioa1_Init(){
RCC->AHB1ENR |= 0x01; // 1: IO port A clock enabled
//RCC->AHB1ENR |= 0x10; // 1: IO port E clock enabled
// APB1 peripheral reset register
RCC->APB1ENR |= 0x01; // 1: enable TIM2
// GPIO port mode register (GPIOx_MODER)
GPIOA->MODER |= 0x00000008; // 10: Alternate function mode PA1 => AF mode
GPIOA->AFR[0] |= 0x00000010; // 1000: Must refer to AF1 (alternate function for TIM1/ TIm2)
GPIOA->PUPDR |= 0x00000008; // Sets pull down resistor for PA1
// CCMR!: capture/compare mode register 1
TIM2->CCMR1 |= 0x0100; // CC2 channel is configured as input, IC2 is mapped on TI2
// SMCR: Slave Mode control register
TIM2->SMCR |= 0x0007; // Bits[2:0] 111: External Clock Mode 1 - Rising edges of the selected trigger clock the counter.
TIM2->SMCR |= 0x0060; // Bits[6:4] 110: selected Trigger: Filtered Timer Input 2 (TI2FP2)
TIM2->ARR = 0xFFFF; // Set the timer reset on the highest possible value
TIM2->CR1 |= 0x0001; //0001 Enable Timer
}
Many thanks in advance for your support!
Digital input cannot "trigger" at particular voltage set by the programmers level. But you can use it in the analog mode using ADC "analogue watchdog" mode.
If your micro has a built in comparator (many STM32Fxxxxs have one) you can use it to set the "trigger" voltage.

Stm32 Time Base Interrupt (without any library)

I use Stm32f103c8t6 processor and I want to make 1 second counter. Normaly I dont use tımer update ınterrupt and my counter counts correctly but when I add timer update ınterrupt in code my counter doesnt count correctly. So fast increment. And ı cant remove update interrupt flag (UIF) in TIM1's SR register. If I remove this flag my code is entering infinty loop. I cant any solution for this problem. Thanks for help
This part is bring in startup_stm32f10x_md.s
/**
* #brief This is the code that gets called when the processor receives an
* unexpected interrupt. This simply enters an infinite loop, preserving
* the system state for examination by a debugger.
*
* #param None
* #retval : None
*/
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
b Infinite_Loop -----------------------------> my code is stuck here
.size Default_Handler, .-Default_Handler
And this is a my code.
#include <stddef.h>
#include "stm32f10x.h"
void CLK_Config(){
RCC-> CR = 0x00000000; //CR Reset
RCC-> CR |= 0x00010000; //HSE enable
while(!(RCC-> CR & 0x00020000)); //HSE FLAG control
RCC-> CR |= 0x00080000; //CSS enable
RCC-> CR |= 0x01000000; //PLL On
RCC-> CFGR |= 0x00010000; //HSE Select PLL input
RCC-> CFGR |= 0x001C0000; //PLL Multi With 9 = 72 Mhz
RCC-> CFGR |= 0x00000002; //PLL Select as SYSCLK
RCC-> CFGR |= 0x00000400; //APB1 Clock divided by 2
RCC-> APB1ENR |= 0x18000000; //APB1 BKP Clock Enable
PWR-> CR |= 0x0100; //PWR BKP Access Enable
RCC-> APB2ENR |= 0x00000001; //APB2 AFIO Clock Enable
}
void TIM1_Config(){
RCC-> APB2ENR |= 0x00000800; //TIM1 CLK Enable
TIM1-> CR1 |= 0x0085; //Update Request Source, Counter Enable
TIM1-> DIER = 0x0001; //Update Interrupt Enable
TIM1-> ARR = 0x1F40; //8000 is set as Auto Reload Value
TIM1-> PSC = 0x2327; //9000 is set as Prescaler Value for 1 sn Formula: 1sn=1Hz=(PCLK/(PSC*ARR))
}
void USART1_Config(){
RCC-> APB2ENR |= 0x00000004; //GPIOA CLK Enable
GPIOA-> CRH |= 0x00000AA0; //GPIOA 10,9 Push-Pull Alternate Function 2Mhz
RCC-> APB2ENR |= 0x00004000; //USART1 CLK Enable
USART1-> BRR |= 0x00001D4C; //USART1 Baund Rate 9600
USART1-> CR1 |= 0x000020C8; //USART, TXE Interrupt, TC Interrupt, Transmitter Enable
}
void Interrupt_Config(){
NVIC-> ISER[0] |= 0x02000000; //NVIC TIM1 UP
NVIC-> ISER[1] |= 0x00000020; //NVIC USART1 Global Interrupt
NVIC-> IP[25] = 0x10; //TIM1 UP Interrupt Priority 2. 25th Interrupt
NVIC-> IP[37] = 0x40; //USART1 Global Interrupt Priority 5. 37th Interrupt
}
uint8_t count1sec; // Global variable
int main(void)
{
CLK_Config();
Interrupt_Config();
TIM1_Config();
USART1_Config();
while (1)
{
if(count1sec != 0){
USART1-> DR = count1sec;
}
}
}
void TIM1_UP_IRQHandler(){
TIM1-> SR = 0x00000000;
NVIC-> ICPR[0] = 0x02000000;
count1sec += 1;
}
I'm not able to detect the exact cause of your problem, but I can provide some suggestions and make some guesses.
1) Do not use magic numbers! Use predefined bit names. Here is an example:
USART2->BRR = 0x1a0; // 115200 bps # 24 MHz (OVER8=1, ONEBIT=1)
USART2->CR1 |= USART_CR1_OVER8 // Oversampling is reduced for higher baud rates
| USART_CR1_IDLEIE // Idle line detection interrupt is enabled
| USART_CR1_TE // Transmitter is enabled
| USART_CR1_RE; // Receiver is enabled
USART2->CR3 |= USART_CR3_ONEBIT // One bit mode for increased clock deviation tolerance
| USART_CR3_DMAT // DMA for TX
| USART_CR3_DMAR; // DMA for RX
USART2->CR1 |= USART_CR1_UE; // Enable USART2
2) Use CMSIS functions to access NVIC functionality. Here is an example:
NVIC_SetPriority(TIM6_DAC_IRQn, 2);
NVIC_EnableIRQ(TIM6_DAC_IRQn);
3) You have Auto-reload preload enable bit set in TIM1->CR1 register. This normally delays the update of the ARR register until the next update event. I'm not sure how it works during the initial run of the timer, but I suggest to avoid using it until you're sure everything works fine.
4) You normally don't need to clear pending bits in NVIC. I suggest removing that code from the ISR. Clearing the flags in the peripheral registers is all you need and you're already doing it with TIM1->SR = 0 line.
5) The reason you stuck in Infinite_Loop is probably the USART TX interrupt. It gets fired but as you didn't supply a ISR for it, it falls into the Default_Handler. You load DR manually in the main loop, so in this case you don't even need USART TX interrupts.
I have same problem today.
I'm using STM32H743zi.
In my case, after clearing SR, at least 13 'nop' required.
I don't know why.
My final solution is:
void TIM16_IRQHandler(void)
{
TIM16->SR = 0 ;
volatile uint32_t sr = TIM16->SR ;
UNUSED(sr) ;
}
Reading back make it work, but I don't know why.
I try to disable MPU and/or DCACHE, but it have no difference.

STM32F030 PWM Setup Issues

I'm trying to get PWM functioning on two pins of my STM32030R8T6, it's on a Nucleo development board and I'm using Keil. For learning, I've mostly been following the material on this website, but with adaptations as that site uses a different MCU. There really isn't much to setting up the PWM so I'm not quite sure what I've done wrong, I know the timer is working because the on-board LED blinks 1.5 times per second, but when I monitor the Ch1 and Ch2 output pins with my scope I get nothing. I'm pretty sure the pins are correctly set in Alternate Function Push-Pull because they're set the same as the MCO pin which is functioning and showing 24 MHz (Though my cheap scope has some problems determining that...). I've attached all of my relevant and even remotely possibly relevant code. And for your convenience:
UM0360 Reference Manual (STM32F030...)
I'd post links to the Nucleo User Manual and Device Datasheet as well but I can't post more than two links, since this is my first question and my reputation is less than ten.
Any help on what I might be doing wrong is appreciated, I'm sure it's something stupid.
#include "stm32f0xx.h"
void Initializations(void);
int main(void)
{
Initializations();
while(1)
{
/* Toggle onboard LED whenever timer overflows */
if((TIM3->SR & TIM_SR_UIF))
{
TIM3->SR &= ~TIM_SR_UIF;
GPIOA->ODR ^= GPIO_ODR_5;
}
}
}
void Initializations(void)
{
/* CLK CONFIG */
RCC->CFGR |= RCC_CFGR_HPRE_DIV2 |
RCC_CFGR_PPRE_DIV16 |
RCC_CFGR_MCO_SYSCLK |
RCC_CFGR_PLLMUL6;
/* Activate PLL, wait */
RCC->CR |= RCC_CR_PLLON;
while(!(RCC->CR & RCC_CR_PLLRDY));
RCC->CFGR |= RCC_CFGR_SW_PLL;
/* Enable IO CLKs */
RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
/* Enable peripheral CLKs */
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
RCC->APB2ENR |= RCC_APB2ENR_USART1EN;
/* PIN INITIALIZATIONS */
GPIOA->MODER |= GPIO_MODER_MODER5_0 | // Onboard LED (General output)
GPIO_MODER_MODER2_1 | // USART2 TX (Alternate function)
GPIO_MODER_MODER3_1 | // USART2 RX (Alternate function)
GPIO_MODER_MODER6_1 | // TIM3 CH1 (Alternate function)
GPIO_MODER_MODER7_1 | // TIM3 CH2 (Alternate function)
GPIO_MODER_MODER8_1 | // MCO (Alternate function)
GPIO_MODER_MODER9_1 | // USART1 TX (Alternate function)
GPIO_MODER_MODER10_1; // USART1 RX (Alternate function)
/* TIMER INITS */
TIM3->PSC = 7;
TIM3->ARR = 59999;
/* CCM1 */
TIM3->CCMR1 |= TIM_CCMR1_OC1M_0 |
TIM_CCMR1_OC1M_1;
TIM3->CCR1 |= 4499;
TIM3->CCER |= TIM_CCER_CC1E; // Enable Ch1
/* CCM2 */
TIM3->CCMR1 |= TIM_CCMR1_OC2M_0 |
TIM_CCMR1_OC2M_1;
TIM3->CCR2 |= 29999;
TIM3->CCER |= TIM_CCER_CC2E; // Enable Ch2
TIM3->CR1 |= TIM_CR1_CEN; // Enable TIM3
/* USART INITS */
RCC->CFGR3 |= RCC_CFGR3_USART1SW_0; // Clock USART1 from SYSCLK
}
In addition to setting the pin to use an alternate function, you must also set which alternate function to use.
This is described in section 8.3.2 (pdf page 128) of the document you linked.
These are the AFRL (for pins 0-7) and AFRH (for pins 8-15) registers on the port.
For example, based on your code, and if TIM3 uses alternate function 2 and is on pins 6 and 7, (and assuming the alternate code was currently 0) you'd do
GPIOA->AFRL |= (2 << (6 * 4)) | (2 << (7 * 4));
If it isn't 0 or you want to be sure, mask off the bits first (each pin gets 4 bits).
(Note, your header may name registers differently than mine, and your alternate functions may also be different; I usually work with STM32F407 or STM32F334. To find the table of alternate functions to see which one you need, you'll have to look that up in the datasheet for the particular chip you are using, as opposed to the family reference manual which you linked above)
The more general form is
mode << (pin * 4)
for AFRL and
mode << ((pin - 8) * 4)
for AFRH.

Resources