Merge pull request #429 from openmv/h7_cpufreq

Update CPU frequency scaling module.
This commit is contained in:
Ibrahim Abd Elkader 2019-01-19 15:59:07 +02:00 committed by GitHub
commit 0f1083d226
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 147 additions and 61 deletions

View File

@ -0,0 +1,24 @@
# CPU frequency scaling example.
#
# This example shows how to use the cpufreq module to change the CPU frequency on the fly.
import sensor, image, time, cpufreq
sensor.reset() # Reset and initialize the sensor.
sensor.set_pixformat(sensor.GRAYSCALE) # Set pixel format to RGB565 (or GRAYSCALE)
sensor.set_framesize(sensor.QQVGA) # Set frame size to QVGA (320x240)
sensor.skip_frames(time = 2000) # Wait for settings take effect.
clock = time.clock() # Create a clock object to track the FPS.
def test_image_processing():
for i in range(0, 50):
clock.tick() # Update the FPS clock.
img = sensor.snapshot() # Take a picture and return the image.
img.find_edges(image.EDGE_CANNY, threshold=(50, 80))
print("\nFrequency Scaling Test...")
for f in cpufreq.get_supported_frequencies():
cpufreq.set_frequency(f)
clock.reset()
test_image_processing()
freqs = cpufreq.get_current_frequencies()
print("CPU Freq:%dMHz HCLK:%dMhz PCLK1:%dMhz PCLK2:%dMhz FPS:%.2f" %(freqs[0], freqs[1], freqs[2], freqs[3], clock.fps()))

View File

@ -1,18 +0,0 @@
# Overclocking Example
#
# This example shows how to overclock your OMV2 cam to 216MHz. The camera will
# stay overclocked until the next hard reset, if you need to keep this frequency
# call the set_frequency function from your main script.
#
# WARNING: Overclocking to 216MHz should be safe, however Use at your own risk!
import cpufreq
# Print current CPU frequency
print(cpufreq.get_frequency())
# Set frequency valid values are (120, 144, 168, 192, 216)
cpufreq.set_frequency(cpufreq.CPUFREQ_216MHZ)
# Print current CPU frequency
print(cpufreq.get_frequency())

View File

@ -3,7 +3,7 @@
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
* This work is licensed under the MIT license, see the file LICENSE for details.
*
* CPU frequency module.
* CPU frequency scaling module.
*
*/
@ -13,58 +13,138 @@
#include <math.h>
#include STM32_HAL_H
#include "py_cpufreq.h"
#include "py_helper.h"
enum cpufreq_freqs {
CPUFREQ_120MHZ=0,
CPUFREQ_144MHZ=1,
CPUFREQ_168MHZ=2,
CPUFREQ_192MHZ=3,
CPUFREQ_216MHZ=4,
CPUFREQ_MAX
};
#if defined(STM32F7) || defined(STM32H7)
#define ARRAY_LENGTH(x) (sizeof(x)/sizeof(x[0]))
#if defined(STM32H7)
static const uint32_t cpufreq_freqs[] = {100, 200, 400};
#elif defined(STM32F7)
static const uint32_t cpufreq_pllq[] = {5, 6, 7, 8, 9};
static const uint32_t cpufreq_freq[] = {120, 144, 168, 192, 216};
static const uint32_t cpufreq_freqs[] = {120, 144, 168, 192, 216};
static const uint32_t cpufreq_latency[] = { // Flash latency (see table 11)
FLASH_LATENCY_3, FLASH_LATENCY_4, FLASH_LATENCY_5, FLASH_LATENCY_7, FLASH_LATENCY_7
};
#endif
void py_cpufreq_init0()
uint32_t cpufreq_get_cpuclk()
{
uint32_t cpuclk = HAL_RCC_GetSysClockFreq();
#if defined(STM32H7)
uint32_t flatency;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
HAL_RCC_GetClockConfig(&RCC_ClkInitStruct, &flatency);
switch (RCC_ClkInitStruct.SYSCLKDivider) {
case RCC_SYSCLK_DIV1:
break;
case RCC_SYSCLK_DIV2:
cpuclk /= 2;
break;
case RCC_SYSCLK_DIV4:
cpuclk /= 4;
break;
default:
break;
}
#endif
return cpuclk;
}
mp_obj_t py_cpufreq_get_frequency()
mp_obj_t py_cpufreq_get_current_frequencies()
{
mp_obj_t tuple[4] = {
mp_obj_new_int(HAL_RCC_GetSysClockFreq()),
mp_obj_new_int(HAL_RCC_GetHCLKFreq()),
mp_obj_new_int(HAL_RCC_GetPCLK1Freq()),
mp_obj_new_int(HAL_RCC_GetPCLK2Freq()),
mp_obj_new_int(cpufreq_get_cpuclk() / (1000000)),
mp_obj_new_int(HAL_RCC_GetHCLKFreq() / (1000000)),
mp_obj_new_int(HAL_RCC_GetPCLK1Freq() / (1000000)),
mp_obj_new_int(HAL_RCC_GetPCLK2Freq() / (1000000)),
};
return mp_obj_new_tuple(4, tuple);
}
mp_obj_t py_cpufreq_set_frequency(mp_obj_t cpufreq_idx_obj)
mp_obj_t py_cpufreq_get_supported_frequencies()
{
mp_obj_t freq_list = mp_obj_new_list(0, NULL);
for (int i=0; i<ARRAY_LENGTH(cpufreq_freqs); i++) {
mp_obj_list_append(freq_list, mp_obj_new_int(cpufreq_freqs[i]));
}
return freq_list;
}
mp_obj_t py_cpufreq_set_frequency(mp_obj_t cpufreq_obj)
{
RCC_ClkInitTypeDef RCC_ClkInitStruct;
#if defined(STM32F7)
RCC_OscInitTypeDef RCC_OscInitStruct;
#endif
// Check CPU frequency index range
uint32_t cpufreq_idx = mp_obj_get_int(cpufreq_idx_obj);
if (cpufreq_idx < 0 || cpufreq_idx >= CPUFREQ_MAX) {
// Check if frequency is supported
int cpufreq_idx = -1;
uint32_t cpufreq = mp_obj_get_int(cpufreq_obj);
for (int i=0; i<ARRAY_LENGTH(cpufreq_freqs); i++) {
if (cpufreq == cpufreq_freqs[i]) {
cpufreq_idx = i;
break;
}
}
// Frequency is Not supported.
if (cpufreq_idx == -1) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported frequency!"));
}
// Return if frequency hasn't changed
if (cpufreq_freq[cpufreq_idx] == (HAL_RCC_GetSysClockFreq()/1000000)) {
// Return if frequency hasn't changed.
if (cpufreq == (cpufreq_get_cpuclk()/(1000000))) {
return mp_const_true;
}
#if defined(STM32H7)
uint32_t flatency = FLASH_LATENCY_2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK |
RCC_CLOCKTYPE_D1PCLK1 | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2 | RCC_CLOCKTYPE_D3PCLK1);
switch (cpufreq) {
case 100:
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV4; // D1CPRE
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1; // HPRE
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1; // D2PPRE1
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV1; // D2PPRE2
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV1; // D1PPRE
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV1; // D3PPRE
break;
case 200:
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV2; // D1CPRE
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1; // HPRE
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; // D2PPRE1
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; // D2PPRE2
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; // D1PPRE
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; // D3PPRE
break;
case 400:
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; // D1CPRE
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; // HPRE
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; // D2PPRE1
RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; // D2PPRE2
RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2; // D1PPRE
RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; // D3PPRE
break;
default:
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Unsupported frequency!"));
break;
}
#elif defined(STM32F7)
// Select HSE as system clock source
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK |
RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2);
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
// Configure the HCLK, PCLK1 and PCLK2 clocks dividers
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
@ -80,7 +160,7 @@ mp_obj_t py_cpufreq_set_frequency(mp_obj_t cpufreq_idx_obj)
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 12; // depends on HSE
RCC_OscInitStruct.PLL.PLLN = cpufreq_freq[cpufreq_idx] * 2;
RCC_OscInitStruct.PLL.PLLN = cpufreq_freqs[cpufreq_idx] * 2;
RCC_OscInitStruct.PLL.PLLP = 2;
RCC_OscInitStruct.PLL.PLLQ = cpufreq_pllq[cpufreq_idx];
@ -90,30 +170,34 @@ mp_obj_t py_cpufreq_set_frequency(mp_obj_t cpufreq_idx_obj)
}
// Select PLL as system clock source
uint32_t flatency = cpufreq_latency[cpufreq_idx];
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, cpufreq_latency[cpufreq_idx]) != HAL_OK) {
#endif
if(HAL_RCC_ClockConfig(&RCC_ClkInitStruct, flatency) != HAL_OK) {
// Initialization Error
nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "RCC CLK Initialization Error!!"));
}
// Do a soft-reset ?
//nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Frequency is set!"));
return mp_const_true;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_cpufreq_get_frequency_obj, py_cpufreq_get_frequency);
STATIC MP_DEFINE_CONST_FUN_OBJ_1(py_cpufreq_set_frequency_obj, py_cpufreq_set_frequency);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_cpufreq_get_current_frequencies_obj, py_cpufreq_get_current_frequencies);
STATIC MP_DEFINE_CONST_FUN_OBJ_0(py_cpufreq_get_supported_frequencies_obj, py_cpufreq_get_supported_frequencies);
#endif // defined(STM32F7) || defined(STM32H7)
static const mp_map_elem_t globals_dict_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_cpufreq) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CPUFREQ_120MHZ), MP_OBJ_NEW_SMALL_INT(CPUFREQ_120MHZ) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CPUFREQ_144MHZ), MP_OBJ_NEW_SMALL_INT(CPUFREQ_144MHZ) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CPUFREQ_168MHZ), MP_OBJ_NEW_SMALL_INT(CPUFREQ_168MHZ) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CPUFREQ_192MHZ), MP_OBJ_NEW_SMALL_INT(CPUFREQ_192MHZ) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_CPUFREQ_216MHZ), MP_OBJ_NEW_SMALL_INT(CPUFREQ_216MHZ) },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_frequency), (mp_obj_t)&py_cpufreq_get_frequency_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_frequency), (mp_obj_t)&py_cpufreq_set_frequency_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_cpufreq) },
#if defined(STM32F7) || defined(STM32H7)
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_frequency), (mp_obj_t)&py_cpufreq_set_frequency_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_current_frequencies), (mp_obj_t)&py_cpufreq_get_current_frequencies_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_supported_frequencies), (mp_obj_t)&py_cpufreq_get_supported_frequencies_obj },
#else
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_frequency), (mp_obj_t)&py_func_unavailable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_current_frequencies), (mp_obj_t)&py_func_unavailable_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_get_supported_frequencies), (mp_obj_t)&py_func_unavailable_obj },
#endif
{ NULL, NULL },
};
STATIC MP_DEFINE_CONST_DICT(globals_dict, globals_dict_table);

View File

@ -337,13 +337,9 @@ Q(bssid)
// cpufreq Module
Q(cpufreq)
Q(CPUFREQ_120MHZ)
Q(CPUFREQ_144MHZ)
Q(CPUFREQ_168MHZ)
Q(CPUFREQ_192MHZ)
Q(CPUFREQ_216MHZ)
Q(get_frequency)
Q(set_frequency)
Q(get_current_frequencies)
Q(get_supported_frequencies)
// Get Pixel
Q(get_pixel)