#include "link.h"
#include "stm32f411.h"
-const char msg[] = "blink ";
-
-static void
-delay (void)
-{
- volatile unsigned int i;
- for (i = 0; i < 500000; i++);
-}
+static const char *text[] = {
+ "hello, friend.\r\n",
+ "hello, friend?\r\n",
+ "that's lame.\r\n",
+ "maybe i should give you a name.\r\n",
+ "but that's a slippery slope.\r\n",
+ "you're only in my head.\r\n",
+ "we have to remember that.\r\n",
+ "shit.\r\n",
+ "it's actually happening, i'm talking to an imaginary person.\r\n\n"
+};
static void
reset_handler (void)
{
unsigned int *src, *dst;
- unsigned int off;
+ unsigned int line, off;
- /* relocate .data to sram */
+ /* Relocate .data section to SRAM */
src = &_data_lma_start;
dst = &_data_vma_start;
while (dst < &_data_vma_end)
*(dst++) = *(src++);
- /* initialize .bss */
+ /* Initialize .bss section */
dst = &_bss_vma_start;
while (dst < &_bss_vma_end)
*(dst++) = 0;
- /* (todo) usart pin setup (alt func and enable port clock) */
+ /* SYSCLK setup --------------------------------------------------------- */
+
+ /* HSEBYP: HSE clock bypass */
+ *RCC_CR &= ~(1u << 18); /* 0: HSE oscillator not bypassed */
+ /* HSEON: HSE clock enable */
+ *RCC_CR |= (1u << 16); /* 1: HSE oscillator ON */
+ /* HSERDY: HSE clock ready flag */
+ while (!(*RCC_CR & (1u << 17))); /* 0: HSE oscillator not ready */
+ /* SW: System clock switch */
+ *RCC_CFGR &= ~(0b11u); /* Clear SW bits */
+ *RCC_CFGR |= (0b01u); /* 01: HSE oscillator selected as system clock */
+ /* SWS: System clock switch status */
+ while ((*RCC_CFGR & (0b11u << 2)) != (0b01u << 2)); /* 01: HSE oscillator used
+ as the system clock */
+ /* HSION: Internal high-speed clock enable */
+ *RCC_CR &= ~(1u); /* 0: HSI oscillator OFF */
+
+ /* UART setup ----------------------------------------------------------- */
+
+ /* GPIOAEN: IO port A clock enable */
+ *RCC_AHB1ENR |= (1u); /* 1: IO port A clock enabled */
+ /* MODERy[1:0]: Port x configuration bits (y = 0..15) */
+ *GPIOA_MODER &= ~(0b1111u << 18); /* Clear PA9 and PA10 bits */
+ *GPIOA_MODER |= (0b1010u << 18); /* 10: Alternate function mode */
+ /* AFRHy: Alternate function selection for port x bit y (y = 8..15) */
+ *GPIOA_AFRH &= ~(0b11111111u << 4); /* Clear PA9 and PA10 bits */
+ *GPIOA_AFRH |= (0b01110111u << 4); /* 0111: AF7 */
+ /* PA9: USART1_TX
+ * PA10: USART1_RX */
+
+ /* USART1EN: USART1 clock enable */
+ *RCC_APB2ENR |= (1u << 4); /* 1: USART1 clock enabled */
/* UE: USART enable */
- *USART_CR1 |= (1u << 13); /* 1: USART enable */
+ *USART1_CR1 |= (1u << 13); /* 1: USART enable */
/* M: Word length */
- *USART_CR1 &= ~(1u << 12); /* 0: 1 Start bit, 8 Data bits, n Stop bit */
+ *USART1_CR1 &= ~(1u << 12); /* 0: 1 Start bit, 8 Data bits, n Stop bit */
+ /* PCE: Parity control enable */
+ *USART1_CR1 &= ~(1u << 10); /* 0: Parity control disabled */
/* STOP: STOP bits */
- *USART_CR2 &= ~(3u << 12); /* 00: 1 Stop bit */
- /* the clock frequnecy is 16mhz initially, so for a baud rate of 115.2 KBps we
- * need to set USARTDIV=8.6875 */
- *USART_BRR = (8u << 4) | 11; /* mantissa and fraction (/16) */
+ *USART1_CR2 &= ~(0b11u << 12); /* 00: 1 Stop bit */
+ /* Clock frequency: 25MHz
+ * Desired baud rate: 1.2 KBps
+ * USARTDIV = 1302.0625 */
+ *USART1_BRR = (1302u << 4) | 1u; /* mantissa and fraction (/16) */
/* TE: Transmitter enable */
- *USART_CR1 |= (1u << 3); /* 1: Transmitter is enabled */
+ *USART1_CR1 |= (1u << 3); /* 1: Transmitter is enabled */
+
+ /* LED setup ------------------------------------------------------------ */
+
+ /* GPIOCEN: IO port C clock enable */
+ *RCC_AHB1ENR |= (1u << 2); /* 1: IO port C clock enabled */
+ /* MODERy[1:0]: Port x configuration bits (y = 0..15) */
+ *GPIOC_MODER &= ~(0b11u << 26); /* Clear PC13 bits */
+ *GPIOC_MODER |= (1u << 26); /* 01: General purpose output mode */
+
+ /* PC13: 0 = LED on
+ * 1 = LED off */
- /* blink blink setup */
- *RCC_AHB1ENR |= (1u << 2);
- *GPIOC_MODER &= ~(3u << 26);
- *GPIOC_MODER |= (1u << 26);
+ /* Test UART and LED ---------------------------------------------------- */
while (1)
{
- /* speak */
- off = 0;
- do
+ for (line = 0; line < sizeof text / sizeof *text; ++line)
{
- /* TXE: Transmit data register empty */
- if (!(*USART_SR & (1u << 7)))
- continue;
+ /* Print current line */
+ off = 0;
+ while (text[line][off])
+ {
+ /* TXE: Transmit data register empty */
+ while (!(*USART1_SR & (1u << 7))); /* 0: Data is not transferred
+ to the shift register */
- *USART_DR = msg[off++];
- }
- while (off < sizeof msg);
+ /* DR[8:0]: Data value */
+ *USART1_DR = text[line][off++];
+ }
+
+ /* TC: Transmission complete */
+ while (!(*USART1_SR & (1u << 6))); /* 0: Transmission is not
+ complete */
- /* blink */
- *GPIOC_ODR ^= (1u << 13);
- delay ();
+ /* Blink LED */
+ *GPIOC_ODR ^= (1u << 13);
+ }
}
}