Direct register access?

The official STMicroelectronics Arduino core
Post Reply
jeffs555
Posts: 12
Joined: Tue Mar 12, 2019 3:42 pm
Answers: 1

Direct register access?

Post by jeffs555 » Wed Mar 13, 2019 10:33 am

I am a retired hardware engineer and like to directly access internal registers when necessary. Using a blue pill F103C8, had no problems with the libMaple based cores, but can't seem to make it work on the STM core. Code compiles without errors on the STM core, but register reads and writes don't seem to work.

For example, I am using "xxx = TIM1->CCR1" to read the Timer1 channel 1 capture/compare register and "TIM1->PSC=10" to set timer1 prescale.

This works fine with the libMaple cores, and compiles without errors on the STM core.
However, on the STM core, reads to any register always returns zero, and the writes don't work either.

Have also tried "xxx=LL_TIM_ReadReg(TIM1, CCR1)" "LL_TIM_WriteReg(TIM1,PSC,10)" and
"xxx=READ_REG(TIM1->CCR1)" "WRITE_REG(TIM1->PSC,10)" with the same negative results. Compiles, but still reads all registers as zero.


What am I doing wrong?
by jeffs555 » Fri Mar 15, 2019 3:37 pm
Thanks all for the responses. I didn't really want to, but downloaded the HAL documentation and tried a simple timer setup. I discovered like you said that after doing a HAL_TIM_Base_Init for a timer, I was able to use "TIMx->reg" to directly access the registers for that timer.

PS Was happy to see all the responses. Was disappointed that I couldn't register for the old forum and hope that this one takes off quickly.
Go to full post

User avatar
Vassilis
Posts: 149
Joined: Wed Feb 27, 2019 5:09 pm
Answers: 2
Location: Thessaloniki, Greece
OS: Linux, Win10, MacOS
IDE: Arduino 1.8.9
Core: Roger, STM official
Board: Bluepill, Maple mini, STM32F4xx
Contact:

Re: Direct register access?

Post by Vassilis » Thu Mar 14, 2019 4:53 pm

Could you post a full source code example ?
-Vassilis Serasidis

User avatar
Rick Kimball
Posts: 71
Joined: Thu Mar 14, 2019 6:27 pm
Location: Eastern NC, US
OS: Linux
IDE: Arduino 1.8.9, vscode+make, eclipse, vi, emacs
Core: libmaple, STM official, fabooh, none
Board: Bluepill, Nucleos, Discovery
Contact:

Re: Direct register access?

Post by Rick Kimball » Thu Mar 14, 2019 6:51 pm

jeffs555 wrote:
Wed Mar 13, 2019 10:33 am
What am I doing wrong?
I have a personal arduino core I use to do register direct access. Here is some example Timer capture code using direct register access and the TIM2 CCR1 in input capture mode. It uses PA0 for input and you can use the PA1 output as a 30usec pulse input. A jumper works between them but it probably safer to use a resistor. The Serial output shows you the duration of the positive pulse.

Things to note about my core and this example. 1.) In my _init() code I enable all the system clocks I'm using (you don't see that in the following code). 2.) You also won't see the code I use for doing USART serial. However, the meat of the examples shows just about the minimum required to use input capture. 3.) My core doesn't use any of the HAL or LL code. It only uses the CMSIS device header (stm32f103xb.h)

Code: Select all

/*
fabooh - TIM2CH1 input capture from PA0

Desc: capture positive pulse in usecs from PA0

input: PA0
output: PA1 ~30usec pulse
*/

serial_default_t<115200, F_CPU, TX_PIN, NO_PIN> Serial;

volatile uint16_t pulse_in_usec;

PA0 PA0_;
PA1 PA1_;

static void input_timer_setup()
{
  RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;

  pinMode(PA0_, INPUT_PULLDOWN);
  
  NVIC_EnableIRQ(TIM2_IRQn);        // Enable TIM2 IRQ

  TIM2->CR1 = 0;                    // disable TIM2, required to configure
  TIM2->CR2 = 0;
  TIM2->SMCR = 0;
  TIM2->DIER = TIM_DIER_CC1IE;      // interrupt enable on CCR1 input
  TIM2->EGR = 0;
  TIM2->CCMR1 = TIM_CCMR1_CC1S_0    // CCR1 as input capture
                | (0b011 << TIM_CCMR1_IC1F_Pos) // 8 samples b4 trigger
                ;
  TIM2->CCMR2 = 0;
  TIM2->CCER = TIM_CCER_CC1E;       // enable CCR1 rising input capture
  TIM2->PSC = (F_CPU/1000000)-1;    // make each TIM2 CNT tick 1 microsecond
  TIM2->ARR = 0xFFFF;               // count from 0 - 65535, then wrap (~6,4 msec max)
  TIM2->DCR = 0;
  TIM2->CR1 = TIM_CR1_CEN;          // enable TIM2
}

void setup() {
  Serial.begin(115200);

  pinMode(PA1_, OUTPUT);
  input_timer_setup();

  delay(1);
}

void loop(){
  /* put a jumper between PA1 and PA0 * to get a ~30 usec pulse */
  PA1_.high();
  delay_us(30);
  PA1_.low();
  delay(100);
  Serial << "pulse_in_usec=" << pulse_in_usec << " usecs" << endl;
}

static void handle_tim2ch1_inputcapture(void) 
{
  static uint16_t channel_1_start;

  // read PA0, if PA0 is high, grab start time & setup falling capture
  // regardless, we have to flip the capture bit polarity to capture next edge
  if ( READ_BIT(GPIOA->IDR, (1<<0)) ) { // read PA0 pin
    channel_1_start = TIM2->CCR1;
    SET_BIT(TIM2->CCER,TIM_CCER_CC1P); // set capture to falling edge
  }
  else {
    pulse_in_usec = TIM2->CCR1 - channel_1_start;
    CLEAR_BIT(TIM2->CCER,TIM_CCER_CC1P); // set capture to rising edge
  }
  // NOTE: reading CCR1 clears the TIM2->SR CC1IF flag
  // bonus! that means we don't have to clear it explicitly
}

// override the default TIM2 interrupt handler
// and look and handle TIM2CH1 input capture events
extern "C" void TIM2_IRQHandler()
{
  // if an edge trigger or an overflow occurs do something
  if ( READ_BIT(TIM2->SR,(TIM_SR_CC1IF|TIM_SR_CC1OF)) ) {
    handle_tim2ch1_inputcapture();
    return;
  }

  while(1); // trap any interrupt flags we don't know about
            // use the debugger to figure it out.
}
-rick

User avatar
BennehBoy
Posts: 67
Joined: Tue Mar 05, 2019 7:43 pm
Location: Yorkshire
OS: Windows 10
IDE: 1.8.9, Sloeber
Core: Roger's & STM
Board: Blue/Blackpill, MM, HYTiny, Black407Z/VET6, DiyMroe, FK407M1
Contact:

Re: Direct register access?

Post by BennehBoy » Fri Mar 15, 2019 12:10 pm

"your Core"? Tell us more Rick....
-Ben

stevestrong
Posts: 60
Joined: Tue Mar 05, 2019 7:49 am
Location: Munich
OS: Win7 & 10
IDE: Arduino 1.8.8, Sloeber
Core: Libmaple
Board: Bluepill, Generic F4VET6 black & mini
Contact:

Re: Direct register access?

Post by stevestrong » Fri Mar 15, 2019 12:15 pm

In ST core you always have to switch on the corresponding interface clock before accessing the interface registers.
In libmaple core this is done in the start up phase, but not in the ST core.

jeffs555
Posts: 12
Joined: Tue Mar 12, 2019 3:42 pm
Answers: 1

Re: Direct register access?

Post by jeffs555 » Fri Mar 15, 2019 3:37 pm

Thanks all for the responses. I didn't really want to, but downloaded the HAL documentation and tried a simple timer setup. I discovered like you said that after doing a HAL_TIM_Base_Init for a timer, I was able to use "TIMx->reg" to directly access the registers for that timer.

PS Was happy to see all the responses. Was disappointed that I couldn't register for the old forum and hope that this one takes off quickly.

Post Reply