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