@@ -90,7 +90,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_bootloader_obj, pyb_bootloader);
9090
9191/// \function info([dump_alloc_table])
9292/// Print out lots of information about the board.
93- STATIC mp_obj_t pyb_info (uint n_args , const mp_obj_t * args ) {
93+ STATIC mp_obj_t pyb_info (mp_uint_t n_args , const mp_obj_t * args ) {
9494 // get and print unique id; 96 bits
9595 {
9696 byte * id = (byte * )0x1fff7a10 ;
@@ -124,7 +124,7 @@ STATIC mp_obj_t pyb_info(uint n_args, const mp_obj_t *args) {
124124
125125 // qstr info
126126 {
127- uint n_pool , n_qstr , n_str_data_bytes , n_total_bytes ;
127+ mp_uint_t n_pool , n_qstr , n_str_data_bytes , n_total_bytes ;
128128 qstr_pool_info (& n_pool , & n_qstr , & n_str_data_bytes , & n_total_bytes );
129129 printf ("qstr:\n n_pool=%u\n n_qstr=%u\n n_str_data_bytes=%u\n n_total_bytes=%u\n" , n_pool , n_qstr , n_str_data_bytes , n_total_bytes );
130130 }
@@ -164,19 +164,105 @@ STATIC mp_obj_t pyb_unique_id(void) {
164164}
165165STATIC MP_DEFINE_CONST_FUN_OBJ_0 (pyb_unique_id_obj , pyb_unique_id );
166166
167- /// \function freq()
168- /// Return a tuple of clock frequencies: (SYSCLK, HCLK, PCLK1, PCLK2).
169- // TODO should also be able to set frequency via this function
170- STATIC mp_obj_t pyb_freq (void ) {
171- mp_obj_t tuple [4 ] = {
172- mp_obj_new_int (HAL_RCC_GetSysClockFreq ()),
173- mp_obj_new_int (HAL_RCC_GetHCLKFreq ()),
174- mp_obj_new_int (HAL_RCC_GetPCLK1Freq ()),
175- mp_obj_new_int (HAL_RCC_GetPCLK2Freq ()),
176- };
177- return mp_obj_new_tuple (4 , tuple );
167+ /// \function freq([sys_freq])
168+ ///
169+ /// If given no arguments, returns a tuple of clock frequencies:
170+ /// (SYSCLK, HCLK, PCLK1, PCLK2).
171+ ///
172+ /// If given an argument, sets the system frequency to that value in Hz.
173+ /// Eg freq(120000000) gives 120MHz. Note that not all values are
174+ /// supported and the largest supported frequency not greater than
175+ /// the given sys_freq will be selected.
176+ STATIC mp_obj_t pyb_freq (mp_uint_t n_args , const mp_obj_t * args ) {
177+ if (n_args == 0 ) {
178+ // get
179+ mp_obj_t tuple [4 ] = {
180+ mp_obj_new_int (HAL_RCC_GetSysClockFreq ()),
181+ mp_obj_new_int (HAL_RCC_GetHCLKFreq ()),
182+ mp_obj_new_int (HAL_RCC_GetPCLK1Freq ()),
183+ mp_obj_new_int (HAL_RCC_GetPCLK2Freq ()),
184+ };
185+ return mp_obj_new_tuple (4 , tuple );
186+ } else {
187+ // set
188+ mp_int_t wanted_sysclk = mp_obj_get_int (args [0 ]) / 1000000 ;
189+ // search for a valid PLL configuration that keeps USB at 48MHz
190+ for (; wanted_sysclk > 0 ; wanted_sysclk -- ) {
191+ for (mp_uint_t p = 2 ; p <= 8 ; p += 2 ) {
192+ if (wanted_sysclk * p % 48 != 0 ) {
193+ continue ;
194+ }
195+ mp_uint_t q = wanted_sysclk * p / 48 ;
196+ if (q < 2 || q > 15 ) {
197+ continue ;
198+ }
199+ if (wanted_sysclk * p % (HSE_VALUE / 1000000 ) != 0 ) {
200+ continue ;
201+ }
202+ mp_uint_t n_by_m = wanted_sysclk * p / (HSE_VALUE / 1000000 );
203+ mp_uint_t m = 192 / n_by_m ;
204+ while (m < (HSE_VALUE / 2000000 ) || n_by_m * m < 192 ) {
205+ m += 1 ;
206+ }
207+ if (m > (HSE_VALUE / 1000000 )) {
208+ continue ;
209+ }
210+ mp_uint_t n = n_by_m * m ;
211+ if (n < 192 || n > 432 ) {
212+ continue ;
213+ }
214+
215+ // found values!
216+
217+ // let the USB CDC have a chance to process before we change the clock
218+ HAL_Delay (USBD_CDC_POLLING_INTERVAL + 2 );
219+
220+ // set HSE as system clock source to allow modification of the PLL configuration
221+ RCC_ClkInitTypeDef RCC_ClkInitStruct ;
222+ RCC_ClkInitStruct .ClockType = RCC_CLOCKTYPE_SYSCLK ;
223+ RCC_ClkInitStruct .SYSCLKSource = RCC_SYSCLKSOURCE_HSE ;
224+ if (HAL_RCC_ClockConfig (& RCC_ClkInitStruct , FLASH_LATENCY_1 ) != HAL_OK ) {
225+ goto fail ;
226+ }
227+
228+ // re-configure PLL
229+ RCC_OscInitTypeDef RCC_OscInitStruct ;
230+ RCC_OscInitStruct .OscillatorType = RCC_OSCILLATORTYPE_HSE ;
231+ RCC_OscInitStruct .HSEState = RCC_HSE_ON ;
232+ RCC_OscInitStruct .PLL .PLLState = RCC_PLL_ON ;
233+ RCC_OscInitStruct .PLL .PLLSource = RCC_PLLSOURCE_HSE ;
234+ RCC_OscInitStruct .PLL .PLLM = m ;
235+ RCC_OscInitStruct .PLL .PLLN = n ;
236+ RCC_OscInitStruct .PLL .PLLP = p ;
237+ RCC_OscInitStruct .PLL .PLLQ = q ;
238+ if (HAL_RCC_OscConfig (& RCC_OscInitStruct ) != HAL_OK ) {
239+ goto fail ;
240+ }
241+
242+ // set PLL as system clock source
243+ RCC_ClkInitStruct .ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 );
244+ RCC_ClkInitStruct .SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK ;
245+ RCC_ClkInitStruct .AHBCLKDivider = RCC_SYSCLK_DIV1 ;
246+ RCC_ClkInitStruct .APB1CLKDivider = RCC_HCLK_DIV4 ;
247+ RCC_ClkInitStruct .APB2CLKDivider = RCC_HCLK_DIV2 ;
248+ if (HAL_RCC_ClockConfig (& RCC_ClkInitStruct , FLASH_LATENCY_5 ) != HAL_OK ) {
249+ goto fail ;
250+ }
251+
252+ // re-init TIM3 for USB CDC rate
253+ timer_tim3_init ();
254+
255+ return mp_const_none ;
256+
257+ void __fatal_error (const char * msg );
258+ fail :
259+ __fatal_error ("can't change freq" );
260+ }
261+ }
262+ nlr_raise (mp_obj_new_exception_msg (& mp_type_ValueError , "can't make valid freq" ));
263+ }
178264}
179- STATIC MP_DEFINE_CONST_FUN_OBJ_0 (pyb_freq_obj , pyb_freq );
265+ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN (pyb_freq_obj , 0 , 1 , pyb_freq );
180266
181267/// \function sync()
182268/// Sync all file systems.
@@ -336,7 +422,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_have_cdc_obj, pyb_have_cdc);
336422
337423/// \function repl_uart(uart)
338424/// Get or set the UART object that the REPL is repeated on.
339- STATIC mp_obj_t pyb_repl_uart (uint n_args , const mp_obj_t * args ) {
425+ STATIC mp_obj_t pyb_repl_uart (mp_uint_t n_args , const mp_obj_t * args ) {
340426 if (n_args == 0 ) {
341427 if (pyb_stdio_uart == NULL ) {
342428 return mp_const_none ;
0 commit comments