How can I toggle an LED at 5th second of each minute with RTC Alarm? - alarm

I am working STM32F746-Disco Board, and trying to implement an Alarm in register level. I am trying to implement a system such that it toggles the user led at 5th second of each minute. However, my program toggles differentially. For now, I can notice that it toggles for 2 seconds, but I don't know at which second, or minute?
My codes are below:
RTC_Utils.c
/*
* RTC_Utils.c
*
* Created on: Sep 8, 2022
*/
#include "RTC_utils.h"
#include "stm32f746xx.h"
void RTC_Init(void) {
uint32_t readBit;
// __HAL_RCC_RTC_ENABLE();
// Enable write access to the backup domain
if(((RCC->APB1ENR) & (1U << 28)) == 0) {
// Enable power interface clock
RCC->APB1ENR |= (1U << 28);
readBit = RCC->APB1ENR;
//UNUSED(readBit);
}
// Select LSE as RTC clock source
if(((PWR->CR1) & (1U << 8)) == 0) {
PWR->CR1 |= (1U << 8);
// Wait until the backup domain write protection has been disabled
while(((PWR->CR1) & (1U << 8)) == 0);
}
// Reset LSEON and LSEBY before configuring
RCC->BDCR &= ~((1U << 0) | (1U << 2));
RCC->BDCR |= (1U << 16);
RCC->BDCR &= ~(1U << 16);
// Wait until LSE clock is ready
// while(((RCC->BDCR) & (1U << 1)) == 0);
RCC->BDCR |= (1U << 0);
// Select LSE as RTC clock source
RCC->BDCR |= 1U << 8;
RCC->BDCR &= ~(1U << 9);
// Disable power interface clock
RCC->APB1ENR &= ~(1U << 28);
RCC->BDCR |= 1U << 15;
// Remove Write Protection
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// Set INIT bit to 1 in the RTC_ISR register to enter initialization mode
RTC->ISR |= 1U << 7;
// Poll INITF bit of in the RTC_ISR register
while((RTC->ISR & (1U << 6)) == 0);
RTC->CR &= (1U << 6);
// program both the prescaler factors to generate 1 Hz clock
RTC->PRER |= ((2U << 7) - 1) << 16;
RTC->PRER |= (2U << 8) - 1;
// Load the initial time and date values in the shadow registers
RTC->TR |= (1U << 22) | (1U << 21) | (8U << 16) | (4U << 12) | (5U << 8);
RTC->DR |= (2U << 20) | (2U << 16) | (5U << 13) | (0U << 12) | (9U << 8) | (0U << 4) || (8U << 0);
// configure the time format (12 or 24 hours)
RTC->CR &= ~(1U << 6);
// Disable Initialization
RTC->ISR &= ~(1U << 7);
// Enable WPR
RTC->WPR = 0xFF;
}
void RTC_Set_Alarm(void) {
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// Clear ALRAE in RTC_CR to disable Alarm A
RTC->CR &= ~(1U << 8);
// Set off alarm A if the second is 5
RTC->ALRMAR |= 0x5;
// Program the Alarm A registers (RTC_ALRMASSR/RTC_ALRMAR).
// Mask every second option
RTC->ALRMAR |= (1U << 23) | (1U << 15) | (1U << 31);
RTC->ALRMAR &= ~(1U << 7);
RTC->CR |= (1U << 8);
RTC->CR |= 1U << 12;
RTC->WPR = 0xFF;
}
void RTC_Alarm_Enable(void) {
RTC_Init();
RTC_Set_Alarm();
// Configure EXTI17
// Select Triggering Edge
EXTI -> RTSR |= EXTI_RTSR_TR17;
// Interrupt Mask Register
EXTI -> IMR |= EXTI_IMR_IM17;
// Event Mask Register
EXTI -> EMR |= EXTI_EMR_EM17;
// Interrupt Pending Register
EXTI -> PR |= EXTI_PR_PR17;
// Set It Priority Most Urgent
NVIC_EnableIRQ(RTC_Alarm_IRQn);
NVIC_SetPriority(RTC_Alarm_IRQn, 0);
}
void RTC_Alarm_IRQHandler(void) {
if (RTC->ISR & (1U << 8)) {
GPIOI->ODR ^= (1U << 1);
RTC->ISR &= ~(1U << 8); // Clear the flag
}
EXTI -> PR |= EXTI_PR_PR17; // Clear pending interrupt flag
}
What is wrong with my code and what to do to toggle led at the 5th second of each minute? Furthermore, I have some doubts about RTC->TR and RTC->DR registers. What happened if I don't make any adjustments on them and how do they work? When and why we should use them?
Thx in advance for your response.

Related

How to get invisible part of segment register

I want to start virtual technology on my AMD computer. So I need to get the invisible part of the segment register, such as limit, base and attribute to fill the state save area of vmcb. I tried to use the following code to read the invisible part and finished filling the related part, but it always failed with exit code -1 meaning "Invalid guest state in VMCB".
pRegister->selector = Asm_ReadCs() & 0xFFF8;
PCODE_SEGMENT_DESCRIPTOR pCodeSegmentDescriptor = NULL;
switch (((PSEGMENT_SELECTOR) & (pRegister->selector))->TI)
{
case 0:
pCodeSegmentDescriptor = (ULONG64)(Gdtr.base) + (((PSEGMENT_SELECTOR) & (pRegister->selector))->SI) * sizeof(PVOID);
break;
case 1:
pLdt = (ULONG64)(Gdtr.base) + Ldtr * sizeof(PVOID);
pCodeSegmentDescriptor = *pLdt + (((PSEGMENT_SELECTOR) & (pRegister->selector))->SI) * sizeof(PVOID);
break;
}
pRegister->HiddenPart.base = pCodeSegmentDescriptor->BaseAddress_LowPart
| (pCodeSegmentDescriptor->BaseAddress_MiddlePart << 16)
| (pCodeSegmentDescriptor->BaseAddress_HighPart << 24);
pRegister->HiddenPart.limit = pCodeSegmentDescriptor->SegmentLimt_LowPart
| (pCodeSegmentDescriptor->SegmentLimt_HighPart &0xF << 16);
if (pCodeSegmentDescriptor->P == 0)
{
pRegister->HiddenPart.attrib = 0;
}
else
{
pRegister->HiddenPart.attrib = pCodeSegmentDescriptor->A
| (pCodeSegmentDescriptor->R << 1)
| (pCodeSegmentDescriptor->C << 2)
| (pCodeSegmentDescriptor->Reserved_0 << 3)
| (pCodeSegmentDescriptor->Reserved_1 << 4)
| (pCodeSegmentDescriptor->DPL << 5)
| (pCodeSegmentDescriptor->P << 7)
| (pCodeSegmentDescriptor->AVL << 12)
| (pCodeSegmentDescriptor->L << 13)
| (pCodeSegmentDescriptor->D << 14)
| (pCodeSegmentDescriptor->G << 15);
}
I want to know how to get the right invisible part of segment register.

Warning: left shift count >= width of type when reading bytestream into double variable in C++

I'm trying to read a bytestream into a double variable in C++.
So my code for this is the following:
double foo;
foo = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24) | (bytes[44] << 32) | (bytes[5] << 40) | (bytes[6] << 48) | (bytes[7] << 56);
As you can see I'm trying to read in 64 bits. And even though double isn't a fixed size, it should be 64 bits on nearly any machine. (sizeof(double) gives me 8 bytes as size)
But still I get this warning:
Warning: left shift count >= width of type
Can I just ignore that warning - or can I somehow make the size of the double fixed (as I know there is no sizefixed floating point datatype in C/C++)?
Thanks for you help!
I found out a solution for myself - but thanks to all the comments!
I tried memcpy() and that worked fine.
I solved it like this:
foo = bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24) | ((uint64_t)bytes[44] << 32) | ((uint64_t)bytes[5] << 40) | ((uint64_t)bytes[6] << 48) | ((uint64_t)bytes[7] << 56);

C++ Bitwise Operator Understanding Code

a &= ~(1 << 10);
Does the code above actually mean:
a &= (0 << 10);
~ is bitwise inversion (take every 1 and turn it into 0, every 0 into 1), so if you have x = 0b0100 (assume 4 bit integers for a second), then ~x == 0b1011. << is "shift this to the left", so '(1 << 2) == 0b0100`.

AVR C++ will not compare numbers

I've been writing a small library for Arduino that essentially gives me control over timer 0 (yes I know the delay() function uses this timer). I started to notice an issue in the code though. The pre-scaler value is passed through the function when it is called along with a few other things: attachTimeInterrupt(int ttc, int prescaler, void (*f)()). In this function, I have a few if statements that determine if the pre-scaler is equal to a few values, being: 1, 8, 64, 256, 1024. Even if the pre-scaler value is set to one of these numbers, the if statement will still not trigger. The proper ISR for this function does, however trigger if a default pre-scaler is set. Here is my code for that function. Any help would be appreciated.
void TimerZero::attachTimeInterrupt(int ttc, int prescaler, void (*f)()){
DDRB = 0b11111111;
prescaler = 1; //Even if I set this right here, it will still not work.
if(prescaler == 1){
PORTB = 0b11111111; //This tests to see if it has been called
TCCR0B |= (1 << CS00) | (1 << WGM02);
} else if(prescaler == 8) {
TCCR0B |= (1 << CS01) | (1 << WGM02);
} else if(prescaler == 64) {
TCCR0B |= (1 << CS00) | (1 << CS01) | (1 << WGM02);
} else if(prescaler == 256) {
TCCR0B |= (1 << CS02) | (1 << WGM02);
} else if(prescaler == 1024) {
TCCR0B |= (1 << CS00) | (1 << CS02) | (1 << WGM02);
} else {
//Default prescaler
TCCR0B |= (1 << CS00) | (1 << CS02) | (1 << WGM02);
}
TIMSK0 |= (1 << OCIE0A);
ttc = 255;
OCR0A = 255;
sei();
}

Undefined high-order of uint64_t while shifting and masking 32-bit values

I have some undefined behaviour in a seemingly innocuous function which is parsing a double value from a buffer. I read the double in two halves, because I am reasonably certain the language standard says that shifting char values is only valid in a 32-bit context.
inline double ReadLittleEndianDouble( const unsigned char *buf )
{
uint64_t lo = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0];
uint64_t hi = (buf[7] << 24) | (buf[6] << 16) | (buf[5] << 8) | buf[4];
uint64_t val = (hi << 32) | lo;
return *(double*)&val;
}
Since I am storing 32-bit values into 64-bit variables lo and hi, I reasonably expect that the high-order 32-bits of these variables will always be 0x00000000. But sometimes they contain 0xffffffff or other non-zero rubbish.
The fix is to mask it like this:
uint64_t val = ((hi & 0xffffffffULL) << 32) | (lo & 0xffffffffULL);
Alternatively, it seems to work if I mask during the assignment instead:
uint64_t lo = ((buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]) & 0xffffffff;
uint64_t hi = ((buf[7] << 24) | (buf[6] << 16) | (buf[5] << 8) | buf[4]) & 0xffffffff;
I would like to know why this is necessary. All I can think of to explain this is that my compiler is doing all the shifting and combining for lo and hi directly on 64-bit registers, and I might expect undefined behaviour in the high-order 32-bits if this is the case.
Can someone please confirm my suspicions or otherwise explain what is happening here, and comment on which (if any) of my two solutions is preferable?
If you try to shift a char or unsigned char you're leaving yourself at the mercy of the standard integer promotions. You're better off casting the values yourself, before you try to shift them. You don't have to separate the lower and upper halves if you do so.
inline double ReadLittleEndianDouble( const unsigned char *buf )
{
uint64_t val = ((uint64_t)buf[7] << 56) | ((uint64_t)buf[6] << 48) | ((uint64_t)buf[5] << 40) | ((uint64_t)buf[4] << 32) |
((uint64_t)buf[3] << 24) | ((uint64_t)buf[2] << 16) | ((uint64_t)buf[1] << 8) | (uint64_t)buf[0];
return *(double*)&val;
}
All this is necessary only if the CPU is big-endian or if the buffer might not be properly aligned for the CPU architecture, otherwise you can simplify this greatly:
return *(double*)buf;