2 * Copyright © 2012 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
32 /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */
33 uint32_t acr = stm_flash.acr;
35 /* Enable 64-bit access and prefetch */
36 acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN);
39 /* Enable 1 wait state so the CPU can run at 32MHz */
40 /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */
41 acr |= (1 << STM_FLASH_ACR_LATENCY);
44 /* HCLK to 16MHz -> AHB prescaler = /1 */
46 cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE);
47 cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE);
49 while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) !=
50 (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE))
52 #define STM_AHB_PRESCALER 1
54 /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */
56 cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1);
57 cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1);
59 #define STM_APB1_PRESCALER 1
61 /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */
63 cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2);
64 cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2);
66 #define STM_APB2_PRESCALER 1
68 /* Enable power interface clock */
69 stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
71 /* Set voltage range to 1.8V */
73 /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */
74 while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0)
77 /* Configure voltage scaling range */
79 cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS);
80 cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS);
83 /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */
84 while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0)
87 /* Enable HSI RC clock 16MHz */
88 if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) {
89 stm_rcc.cr |= (1 << STM_RCC_CR_HSION);
90 while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY)))
93 #define STM_HSI 16000000
95 /* Switch to direct HSI for SYSCLK */
96 if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) !=
97 (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) {
99 cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
100 cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW);
102 while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) !=
103 (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS))
107 /* Disable the PLL */
108 stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON);
109 while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))
112 /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6, PLLDIV = 4 */
114 cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL);
115 cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV);
117 // cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL);
118 // cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV);
120 cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL);
121 cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV);
126 /* PLL source to HSI */
127 cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC);
129 #define STM_PLLSRC STM_HSI
133 /* Enable the PLL and wait for it */
134 stm_rcc.cr |= (1 << STM_RCC_CR_PLLON);
135 while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)))
138 /* Switch to the PLL for the system clock */
141 cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW);
142 cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW);
145 uint32_t c, part, mask, val;
148 mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS);
149 val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS);
156 #define STM_PLLVCO (STM_PLLSRC * STM_PLLMUL)
157 #define STM_SYSCLK (STM_PLLVCO / STM_PLLDIV)
158 #define STM_HCLK (STM_SYSCLK / STM_AHB_PRESCALER)
159 #define STM_APB1 (STM_HCLK / STM_APB1_PRESCALER)
160 #define STM_APB2 (STM_HCLK / STM_APB2_PRESCALER)
162 #define BAUD_9600 (STM_APB2 / 9600)
170 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN);
172 /* Hook PA9, PA10 to USART1 (AFIO7) */
173 stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE);
174 stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE);
175 stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7);
176 stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7);
179 stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN);
181 /* 9.6KBps. PCLK1 = 16MHz. OVER8 = 0 */
183 /* USARTDIV = PCLK1 / (16 * 9600) = 104.1{6}
184 * round to 104.1875 (1667 / 16)
186 * actual baud rate = 16e6 / (16 * 104.1875) = 9598Bps
189 stm_usart1.brr = BAUD_9600;
191 stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) |
192 (1 << STM_USART_CR1_UE) |
193 (0 << STM_USART_CR1_M) |
194 (0 << STM_USART_CR1_WAKE) |
195 (0 << STM_USART_CR1_PCE) |
196 (0 << STM_USART_CR1_PS) |
197 (0 << STM_USART_CR1_PEIE) |
198 (0 << STM_USART_CR1_TXEIE) |
199 (0 << STM_USART_CR1_TCIE) |
200 (0 << STM_USART_CR1_RXNEIE) |
201 (0 << STM_USART_CR1_IDLEIE) |
202 (1 << STM_USART_CR1_TE) |
203 (1 << STM_USART_CR1_RE) |
204 (0 << STM_USART_CR1_RWU) |
205 (0 << STM_USART_CR1_SBK));
207 stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) |
208 (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) |
209 (0 << STM_USART_CR2_CLKEN) |
210 (0 << STM_USART_CR2_CPOL) |
211 (0 << STM_USART_CR2_CPHA) |
212 (0 << STM_USART_CR2_LBCL) |
213 (0 << STM_USART_CR2_LBDIE) |
214 (0 << STM_USART_CR2_LBDL) |
215 (0 << STM_USART_CR2_ADD));
217 stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) |
218 (0 << STM_USART_CR3_CTSIE) |
219 (0 << STM_USART_CR3_CTSE) |
220 (0 << STM_USART_CR3_RTSE) |
221 (0 << STM_USART_CR3_DMAT) |
222 (0 << STM_USART_CR3_DMAR) |
223 (0 << STM_USART_CR3_SCEN) |
224 (0 << STM_USART_CR3_NACK) |
225 (0 << STM_USART_CR3_HDSEL) |
226 (0 << STM_USART_CR3_IRLP) |
227 (0 << STM_USART_CR3_IREN) |
228 (0 << STM_USART_CR3_EIE));
236 while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE)))
241 int putc( int c, FILE * stream ) {
246 serial_string(char *string)
250 while (c = *string++)
254 volatile uint16_t tick_count;
259 if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) {
265 #define TIMER_10kHz (STM_APB1 / 10000)
270 stm_nvic_set_enable(STM_ISR_TIM6_POS);
271 stm_nvic_set_priority(STM_ISR_TIM6_POS, 1);
273 /* Turn on timer 6 */
274 stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN);
276 stm_tim6.psc = TIMER_10kHz;
280 /* Enable update interrupt */
281 stm_tim6.dier = (1 << STM_TIM67_DIER_UIE);
283 /* Poke timer to reload values */
284 stm_tim6.egr |= (1 << STM_TIM67_EGR_UG);
286 stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS);
289 stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) |
290 (0 << STM_TIM67_CR1_OPM) |
291 (1 << STM_TIM67_CR1_URS) |
292 (0 << STM_TIM67_CR1_UDIS) |
293 (1 << STM_TIM67_CR1_CEN));
302 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN);
303 stm_moder_set(&stm_gpiob, 7, STM_MODER_OUTPUT);
304 stm_moder_set(&stm_gpiob, 6, STM_MODER_OUTPUT);
306 stm_gpiob.odr = (1 << 7);
309 stm_gpiob.odr = (1 << 6);
310 printf ("world %d\n", tick_count);
319 for (i = 0; i < 1000000; i++)
320 __asm__ __volatile__ ("nop\n\t":::"memory");