I am writing a program on STM32F4 Discovery where I have to store address of Timer's CCR register into a pointer and then change register via this pointer, ie
volatile uint32_t* tim_ccr_reg = reinterpret_cast<uint32_t*>(TIM4_BASE + 0x34);
// 0x34 = offset of CCR1 register
*tim_ccr_reg = 1999; // Set CCR1 to 1999
When I test this alone in an "empty program" it works, but when I use my entire program (along with all other features I implemented) it causes hard fault at one of those assignments. Now Im figuring out whether its my other code which displaces something in memory or I'm saving register address the wrong way and it only shows when more complex program is loaded. In documentation I read
The simplest way to implement memory-mapped variables is to use pointers to fixed addresses.
#define PORTBASE 0x40000000
unsigned int volatile * const port = (unsigned int *) PORTBASE;
The variable port is a constant pointer to a volatile unsigned integer, so we can access the memory-mapped register using:
*port = value; /* write to port */
value = *port; /* read from port */
This approach can be used to access 8, 16 or 32 bit registers, but be sure to declare the variable with the appropriate type for its size, i.e., unsigned int for 32-bit registers, unsigned short for 16-bit, and unsigned char for 8-bit. You should also ensure that the memory-mapped registers lie on appropriate address boundaries, e.g. either all word-aligned, or aligned on their natural size boundaries, i.e., 16-bit registers must be aligned on half-word addresses (but note that ARM recommends that all registers, whatever their size, be aligned on word boundaries.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka3750.html
Then I went to see documentation for CCR registers for timers and it says
so now I'm not certain, is the register always 32-bit and only 16-bits are used in some timers or is register in some cases 16-bit only and I have to use 16-bit pointer to write to it?
In any case, I would like to know what is the proper way of saving timer CCR register to a variable. If I second click on CCR1 in following command
TIM4->CCR1 = 1999;
and click "go to definition" it takes me to some weird chunk of code
/** \brief ITM Send Character
This function transmits a character via the ITM channel 0.
It just returns when no debugger is connected that has booked the output.
It is blocking when a debugger is connected, but the previous character send is not transmitted.
\param [in] ch Character to transmit
\return Character to transmit
*/
static __INLINE uint32_t ITM_SendChar (uint32_t ch)
{
if ((CoreDebug->DEMCR & CoreDebug_DEMCR_TRCENA_Msk) && /* Trace enabled */
(ITM->TCR & ITM_TCR_ITMENA_Msk) && /* ITM enabled */
(ITM->TER & (1UL << 0) ) ) /* ITM Port #0 enabled */
{
while (ITM->PORT[0].u32 == 0);
ITM->PORT[0].u8 = (uint8_t) ch;
}
return (ch);
}
Im (very) confused.