cancel
Showing results for 
Search instead for 
Did you mean: 

Accessing HAL TIM struct fields pointers inside other structs correctly.

Posted on April 25, 2017 at 12:21

I have the following structs (from a library I'm using) with some fields and I would like to assign with OR operation a new value. But I'm debugging and I can't see how anything is writing there:

typedef struct { 
TIM_TypeDef *Instance; /*!< Register base address */ 
TIM_Base_InitTypeDef Init; /*!< TIM Time Base required parameters */ 
HAL_TIM_ActiveChannel Channel; /*!< Active channel */ 
DMA_HandleTypeDef *hdma[7]; /*!< DMA Handlers array This array is accessed by a @ref DMA_Handle_index */
HAL_LockTypeDef Lock; /*!< Locking object */ 
__IO HAL_TIM_StateTypeDef State; /*!< TIM operation state */
}TIM_HandleTypeDef; 
typedef struct
{ 
__IO uint32_t CR1; /*!< TIM control register 1, Address offset: 0x00 */
__IO uint32_t CR2; /*!< TIM control register 2, Address offset: 0x04 */
__IO uint32_t SMCR; /*!< TIM slave mode control register, Address offset: 0x08 */ 
__IO uint32_t DIER; /*!< TIM DMA/interrupt enable register, Address offset: 0x0C */ 
__IO uint32_t SR; /*!< TIM status register, Address offset: 0x10 */ 
__IO uint32_t EGR; /*!< TIM event generation register, Address offset: 0x14 */ 
__IO uint32_t CCMR1; /*!< TIM capture/compare mode register 1, Address offset: 0x18 */ 
__IO uint32_t CCMR2; /*!< TIM capture/compare mode register 2, Address offset: 0x1C */ 
__IO uint32_t CCER; /*!< TIM capture/compare enable register, Address offset: 0x20 */ 
__IO uint32_t CNT; /*!< TIM counter register, 
 ... 
} TIM_TypeDef;

I have a part of code where I defined:

 TIM_HandleTypeDef TIMER_Struct;

And I would like to access the field 'CR1' of TIM_TypeDef struct that is '*Instance' field of TIM_HandleTypeDef. So I have done it by this way in a function:

 void DRV_TIMER_init(void) 
{ 
... 
TIMER_Struct.Instance = TIMx;//TIM7
TIMER_Struct.Init.Period = 100 - 1; 
TIMER_Struct.Init.Prescaler = uwPrescalerValue; 
TIMER_Struct.Init.ClockDivision = 0; // these accesses work 
TIMER_Struct.Instance -> CR1 |= 0x01 << 3; // this no works 
... 
}

Even if I write directly:

 TIMER_Struct.Instance -> CR1 = 0xFFFFFFFF; 

It stills without having effect.

I think It could be a fact that I'm not controlling appropiately the pointer access or similar. But I don't see how can I access and modify the content of the commented field. Since I can see (debug mode) how the rest of struct fields updates are writen correctly.

Any correction suggested here?

TIMER_Struct.Instance -> CR1 = 0xFFFFFFFF; 

I try different ways to get it with no success. I need new ideas. How would you do if you want write there?

Thanks in advance.

#pointers #hal-tim-structs
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on April 25, 2017 at 17:58

TIMER_Struct.Instance -> CR1 |= 0x01 << 3; // this no works 


How do you know that 'this no works'?

Has that timers' clock been enabled in its respective RCC_APBxENR?

JW

View solution in original post

13 REPLIES 13
Posted on April 25, 2017 at 17:58

TIMER_Struct.Instance -> CR1 |= 0x01 << 3; // this no works 


How do you know that 'this no works'?

Has that timers' clock been enabled in its respective RCC_APBxENR?

JW

Max
ST Employee
Posted on April 26, 2017 at 04:49

Hello,

When you are having troubles with a peripheral hardware register, you should first read its description in the reference manual of the product you are using.

Hardware registers often have constraints due to their specific implementations.

Also check for examples of this register usage in the library, it will show you how to properly access the register when there are constraints (like for reserved bits, data width constraints, handling of r_w0/

r_w

1, access order constraints ...) 

BR,

Max

Max
ST Employee
Posted on April 26, 2017 at 10:18

the 

TIMER_Struct

.

Instance 

is a pointer to the hardware register, so you are indeed accessing the timer peripheral registers with the code above.

And there are restrictions on this specific register usage.

Posted on April 26, 2017 at 09:58

Jan, thanks for your attention. Timer runs, hence, the only thing I can't get and it's so weird is: writing CR1 register (config register) before initialize the peripheral with HAL_xxx_init(). And I can't update this MCU register, obviously due I'm not able to update my desired value in the 

TIMER_Struct struct I have declared.

How can I see this: I'm debugging and watching TIMER_struct fields after passing write CR1 lines; it has no effect. Timer runs, but now I would like to see how my timer works with some config changes, but I can't change config values coding. That's the question.

I hope you understood me. 

Posted on April 26, 2017 at 10:09

Hi Max I haven't problems exactly with the 'real' registers, so I have problems with struct pointers fields structs accesses. They don't update what I'm writing on.

These structs are provided by st libraries. I guess more people has used them and set config bits more than once.

The fact is that I have read every Tim7 register and other datasheet parts related with this basic timer. URS bit is read/write bit at CR1. However, it doesn't matter, because this register will be updated after a first steep that is: inizialize your struct and then a second: passed it to a function call HAL_xxx_init(). If my struct doesn't have the values I want at desired fields (one of them is call CR1), obviously the real or physical CR1 will not be writen with them. 

Before

HAL_xxx_init()

, when I was debugging I can see how CR1 field of the struct has not experienced any effect. 

regards.

Posted on April 26, 2017 at 10:17

How can I see this: I'm debugging and watching TIMER_struct fields after passing write CR1 lines; it has no effect.

In that very same moment, in the debugger, have a look at the relevant RCC_APBxENR register. Is the relevant TIMxEN bit set?

JW

Posted on April 26, 2017 at 10:37

Thanks for your attention, Max. Where can I find them? I was readig at tim chapter. At register description there is nothing about restrictions on URS bit. I'm not accessing reserved bits.

Cr1 has 16 bits, and CR1 field in the struct has a 32b type. Even I also tried with cast the value to uint_32b due manual said at TIM6/TIM7 register chapter: '

peripheral registers can be written by half-words (16 bits) or words (32 bits)'.

But, no effect. 

Posted on April 26, 2017 at 11:53

Hi Max, I was looking how HaL functions access this register. I found something like this

(where TIM_TypeDef  *TIMx could be equivalent to the 'Instance' of 

TIMER_Struct

.

Instance

:(

uint32_t tmpcr1 = 0;

tmpcr1 = TIMx->CR1;

tmpcr1 &= ~(TIM_CR1_DIR | TIM_CR1_CMS);

tmpcr1 |= Structure->CounterMode;

TIMx->CR1 = tmpcr1;

I think I could have found the kit of this question. I'm not sure if it's so a great difference between:

a) option:

 

Instance

->

CR1

|=

0x01

<<

3

;

// this no works

and b) option:

   tmpcr1 |=

0x01

<<

3;

   TIMx->CR1 = tmpcr1;

but I think they are using aux 32b_t var for some reason. Is it? Do you think are there significant differences between the first way I used a) and the second one b)?

I hope I got the answer... 

Posted on April 26, 2017 at 13:02

I don't find this var in my debug session but the first thing you make me think was about hal_init() function, the place were enable clock and irq. Hence I put the assignment after returning from init(). If this was the question you treated to say me I must say you were OK! Because now I can write this reg. 

I will never forget this lesson. You must first to enable the peripheral clock if you want to write the config registers.