#include <stdio.h>
#include <string.h>
#include <stm32f10x.h>
#define BIT(reg, bit) (((reg) & (bit)) != 0)
struct fifo
{
uint8_t buf[127];
uint8_t front;
uint8_t rear;
} usartbuf;
void fifo_init(struct fifo *f)
{
f->front = f->rear = 0;
}
uint8_t fifo_full(struct fifo *f)
{
return f->front == (f->rear + 1) % sizeof(f->buf);
}
uint8_t fifo_empty(struct fifo *f)
{
return f->front == f->rear;
}
uint8_t fifo_in(struct fifo *f, uint8_t data)
{
if (fifo_full(f))
return 0;
f->buf[f->rear] = data;
f->rear = (f->rear + 1) % sizeof(f->buf);
return 1;
}
uint8_t fifo_out(struct fifo *f, uint8_t *data)
{
if (fifo_empty(f))
return 0;
*data = f->buf[f->front];
f->front = (f->front + 1) % sizeof(f->buf);
return 1;
}
int fputc(int ch, FILE *fp)
{
if (fp == &__stdout)
{
if (ch == '\n')
{
USART1->DR = '\r';
while ((USART1->SR & USART_SR_TXE) == 0);
}
USART1->DR = ch;
while ((USART1->SR & USART_SR_TXE) == 0);
}
return ch;
}
int fgetc(FILE *fp)
{
uint8_t value;
if (fp == &__stdin)
{
while (!fifo_out(&usartbuf, &value));
return value;
}
return 0;
}
int main(void)
{
char str[21];
uint32_t value;
RCC->APB1ENR = RCC_APB1ENR_PWREN | RCC_APB1ENR_BKPEN;
PWR->CR = PWR_CR_DBP;
RCC->BDCR = RCC_BDCR_BDRST; // Backup Domain必須要復位後才能重設RTC時鐘
// HSE/128: 外部大晶振128分頻
//RCC->BDCR = RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL;
// LSE: 外部小晶振
//RCC->BDCR = RCC_BDCR_LSEON;
//while ((RCC->BDCR & RCC_BDCR_LSERDY) == 0);
//RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_0;
// LSI: 內部小晶振
RCC->CSR = RCC_CSR_LSION;
while ((RCC->CSR & RCC_CSR_LSIRDY) == 0);
RCC->BDCR = RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_1;
fifo_init(&usartbuf);
RCC->APB2ENR = RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;
GPIOA->CRH = 0x4b0;
USART1->BRR = 0x271;
USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE;
NVIC_EnableIRQ(USART1_IRQn);
printf("PWR->CR=0x%x, RCC->BDCR=0x%x, RCC->CSR=0x%x\n", PWR->CR, RCC->BDCR, RCC->CSR);
NVIC_EnableIRQ(RTC_IRQn);
while (1)
{
scanf("%20s", str);
if (strcmp(str, "test") == 0)
printf("Hello World!\n");
else if (strcmp(str, "fifopos") == 0)
printf("pos=%d\n", usartbuf.front);
else if (strcmp(str, "get") == 0)
{
scanf("%20s", str);
if (strcmp(str, "RTC_CRH") == 0)
printf("OWIE=%d ALRIE=%d SECIE=%d\n", BIT(RTC->CRH, RTC_CRH_OWIE), BIT(RTC->CRH, RTC_CRH_ALRIE), BIT(RTC->CRH, RTC_CRH_SECIE));
else if (strcmp(str, "RTC_CRL") == 0)
printf("RTOFF=%d CNF=%d RSF=%d OWF=%d ALRF=%d SECF=%d\n", BIT(RTC->CRL, RTC_CRL_RTOFF), BIT(RTC->CRL, RTC_CRL_CNF), BIT(RTC->CRL, RTC_CRL_RSF), BIT(RTC->CRL, RTC_CRL_OWF), BIT(RTC->CRL, RTC_CRL_ALRF), BIT(RTC->CRL, RTC_CRL_SECF));
else if (strcmp(str, "RTC_DIV") == 0)
printf("%d\n", (RTC->DIVH << 16) | RTC->DIVL);
else if (strcmp(str, "RTC_CNT") == 0)
printf("%d\n", (RTC->CNTH << 16) | RTC->CNTL);
else
printf("Unknown register: %s!\n", str);
}
else if (strcmp(str, "set") == 0)
{
scanf("%20s", str);
while ((RTC->CRL & RTC_CRL_RTOFF) == 0);
if (strcmp(str, "RTC_CRH") == 0)
{
scanf("%x", &value);
RTC->CRH = value & 7;
}
else if (strcmp(str, "RTC_CRL") == 0)
{
scanf("%x", &value);
RTC->CRL = value & 0x1f;
}
else if (strcmp(str, "RTC_PRL") == 0)
{
scanf("%d", &value);
RTC->PRLL = value & 0xffff;
RTC->PRLH = (value >> 16) & 0x0f;
}
else if (strcmp(str, "RTC_CNT") == 0)
{
scanf("%d", &value);
RTC->CNTL = value & 0xffff;
RTC->CNTH = (value >> 16) & 0xffff;
}
else if (strcmp(str, "RTC_ALR") == 0)
{
scanf("%d", &value);
RTC->ALRL = value & 0xffff;
RTC->ALRH = (value >> 16) & 0xffff;
}
else
printf("Unknown register: %s!\n", str);
}
else if (str[0] != ';')
printf("Unknown command: %s!\n", str);
}
}
void USART1_IRQHandler(void)
{
if (USART1->SR & USART_SR_RXNE)
fifo_in(&usartbuf, USART1->DR);
}
void RTC_IRQHandler(void)
{
uint8_t data = RTC->CRL;
RTC->CRL &= ~RTC->CRH;
printf("Interrupt triggered: RTC_CRL=0x%x\n", data);
}