AM335x inicializace, rychlost
Jaroslav Buchta
jaroslav.buchta na hascomp.cz
Pondělí Únor 23 06:12:18 CET 2015
Zdravim, zkousel jsem vcera programovat holy CPU, funguje to hezky ale
prijde mi strasne pomaly.
Nejdriv jsem myslel, ze mi nejde nastavit PLL a bezi stale z 25MHz, pak
jsem ale zjistil, ze jsou PLL nastaveny uz boot mloaderem a MPU clk je
500 MHz?
Je mi pak divne, ze milion iteraci jednoducheho cyklu trva skoro
sekundu, v assembleru pri ladeni kod vypada normalne, ze by potreboval
cca 20-30 cyklu a ne 400....
Program bezi z interni RAM, predpokladam, ze je dost rychla, kdyz vypnu
cache, je beh pomalejsi ale jen o malo.
Netusi nekdo, kde je zakopany pes? Zatim neni inicializace kompletni,
muze mit vliv nastaveni ostatnich PLL (LCD, DDR, perif)? ktere ale
nejsou v programu pouzity?
Zdrojak vypada takto (nutno uznat, ze ST ma proti TI naprosto prehledne
knihovny, priklady a zejmena pouzite symboly...)
#include "soc_AM335x.h"
#include "evmAM335x.h"
#include "gpio_v2.h"
#include "hw_control_AM335x.h"
#include "hw_cm_per.h"
#include "hw_types.h"
#include "hw_cm_wkup.h"
#include "device.h"
#include "cache.h"
#include "cp15.h"
/*
**Setting the CORE PLL values at OPP100:
** OSCIN = 25MHz, Fdpll = 2GHz
** HSDM4 = 200MHz, HSDM5 = 250MHz
** HSDM6 = 500MHz
*/
#define COREPLL_M 1000
#define COREPLL_N 24
#define COREPLL_HSD_M4 10
#define COREPLL_HSD_M5 8
#define COREPLL_HSD_M6 4
void CorePLLInit(void)
{
volatile unsigned int regVal = 0;
/* Enable the Core PLL */
/* Put the PLL in bypass mode */
regVal = HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKMODE_DPLL_CORE) &
~CM_WKUP_CM_CLKMODE_DPLL_CORE_DPLL_EN;
regVal |= CM_WKUP_CM_CLKMODE_DPLL_CORE_DPLL_EN_DPLL_MN_BYP_MODE;
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKMODE_DPLL_CORE) = regVal;
while(!(HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_IDLEST_DPLL_CORE) &
CM_WKUP_CM_IDLEST_DPLL_CORE_ST_MN_BYPASS));
/* Set the multipler and divider values for the PLL */
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKSEL_DPLL_CORE) =
((COREPLL_M << CM_WKUP_CM_CLKSEL_DPLL_CORE_DPLL_MULT_SHIFT) |
(COREPLL_N << CM_WKUP_CM_CLKSEL_DPLL_CORE_DPLL_DIV_SHIFT));
/* Configure the High speed dividers */
/* Set M4 divider */
regVal = HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_DIV_M4_DPLL_CORE);
regVal = regVal & ~CM_WKUP_CM_DIV_M4_DPLL_CORE_HSDIVIDER_CLKOUT1_DIV;
regVal = regVal | (COREPLL_HSD_M4 <<
CM_WKUP_CM_DIV_M4_DPLL_CORE_HSDIVIDER_CLKOUT1_DIV_SHIFT);
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_DIV_M4_DPLL_CORE) = regVal;
/* Set M5 divider */
regVal = HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_DIV_M5_DPLL_CORE);
regVal = regVal & ~CM_WKUP_CM_DIV_M5_DPLL_CORE_HSDIVIDER_CLKOUT2_DIV;
regVal = regVal | (COREPLL_HSD_M5 <<
CM_WKUP_CM_DIV_M5_DPLL_CORE_HSDIVIDER_CLKOUT2_DIV_SHIFT);
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_DIV_M5_DPLL_CORE) = regVal;
/* Set M6 divider */
regVal = HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_DIV_M6_DPLL_CORE);
regVal = regVal & ~CM_WKUP_CM_DIV_M6_DPLL_CORE_HSDIVIDER_CLKOUT3_DIV;
regVal = regVal | (COREPLL_HSD_M6 <<
CM_WKUP_CM_DIV_M6_DPLL_CORE_HSDIVIDER_CLKOUT3_DIV_SHIFT);
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_DIV_M6_DPLL_CORE) = regVal;
/* Now LOCK the PLL by enabling it */
regVal = HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKMODE_DPLL_CORE) &
~CM_WKUP_CM_CLKMODE_DPLL_CORE_DPLL_EN;
regVal |= CM_WKUP_CM_CLKMODE_DPLL_CORE_DPLL_EN;
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKMODE_DPLL_CORE) = regVal;
while(!(HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_IDLEST_DPLL_CORE) &
CM_WKUP_CM_IDLEST_DPLL_CORE_ST_DPLL_CLK));
}
#define MPUPLL_M MPUPLL_M_600_MHZ
void MPUPLLInit()
{
volatile unsigned int regVal = 0;
regVal = HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKSEL_DPLL_MPU);
/* Put the PLL in bypass mode */
regVal = HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKMODE_DPLL_MPU) &
~CM_WKUP_CM_CLKMODE_DPLL_MPU_DPLL_EN;
regVal |= CM_WKUP_CM_CLKMODE_DPLL_MPU_DPLL_EN_DPLL_MN_BYP_MODE;
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKMODE_DPLL_MPU) = regVal;
// return;
/* Wait for DPLL to go in to bypass mode */
while(!(HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_IDLEST_DPLL_MPU) &
CM_WKUP_CM_IDLEST_DPLL_MPU_ST_MN_BYPASS));
/* Clear the MULT and DIV field of DPLL_MPU register */
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKSEL_DPLL_MPU) &=
~(CM_WKUP_CM_CLKSEL_DPLL_MPU_DPLL_MULT |
CM_WKUP_CM_CLKSEL_DPLL_MPU_DPLL_DIV);
/* Set the multiplier and divider values for the PLL */
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKSEL_DPLL_MPU) |=
((MPUPLL_M <<
CM_WKUP_CM_CLKSEL_DPLL_MPU_DPLL_MULT_SHIFT) |
(MPUPLL_N <<
CM_WKUP_CM_CLKSEL_DPLL_MPU_DPLL_DIV_SHIFT));
regVal = HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_DIV_M2_DPLL_MPU);
regVal = regVal & ~CM_WKUP_CM_DIV_M2_DPLL_MPU_DPLL_CLKOUT_DIV;
regVal = regVal | 1; //MPUPLL_M2;
/* Set the CLKOUT2 divider */
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_DIV_M2_DPLL_MPU) = regVal;
/* Now LOCK the PLL by enabling it */
regVal = HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKMODE_DPLL_MPU) &
~CM_WKUP_CM_CLKMODE_DPLL_MPU_DPLL_EN;
regVal |= CM_WKUP_CM_CLKMODE_DPLL_MPU_DPLL_EN;
HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_CLKMODE_DPLL_MPU) = regVal;
while(!(HWREG(SOC_CM_WKUP_REGS + CM_WKUP_CM_IDLEST_DPLL_MPU) &
CM_WKUP_CM_IDLEST_DPLL_MPU_ST_DPLL_CLK));
}
int main(void)
{
CorePLLInit();
MPUPLLInit();
CacheEnable(CACHE_ALL);
// CacheDisable(CACHE_ALL);
/* Enabling functional clocks for GPIO1 instance. */
GPIO1ModuleClkConfig();
GPIO1PinMuxSetup(0); // GPIO1_0
GPIO1PinMuxSetup(1); // GPIO1_1
GPIOModuleEnable(SOC_GPIO_1_REGS);
/* Resetting the GPIO module. */
GPIOModuleReset(SOC_GPIO_1_REGS);
/* Setting the GPIO pin as an output pin. */
GPIODirModeSet(SOC_GPIO_1_REGS,
0,
GPIO_DIR_OUTPUT);
/* Setting the GPIO pin as an output pin. */
GPIODirModeSet(SOC_GPIO_1_REGS,
1,
GPIO_DIR_OUTPUT);
volatile int idx;
volatile int x;
int led = 0;
while (1)
{
for (idx=0; idx<500000; idx++)
{
x++;
}
led++;
GPIOPinWrite(SOC_GPIO_1_REGS,
0,
(led & 0x01) ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
GPIOPinWrite(SOC_GPIO_1_REGS,
1,
(led & 0x02) ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
}
return 1;
}
---
This email has been checked for viruses by Avast antivirus software.
http://www.avast.com
Další informace o konferenci Hw-list