⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hal_mcg.c

📁 [拉普兰德]TSL1401线性CCD模块资料包
💻 C
字号:
/*
 * --------------"拉普兰德K60底层库"-----------------
 *
 * 测试硬件平台:LPLD_K60 Card
 * 版权所有:北京拉普兰德电子技术有限公司
 * 网络销售:http://laplenden.taobao.com
 * 公司门户:http://www.lpld.cn
 *
 * 文件名: HAL_MCG.h
 * 用途: MCG底层模块相关函数
 * 最后修改日期: 20120216
 *
 * 开发者使用协议:
 *  本代码面向所有使用者开放源代码,开发者可以随意修改源代码。但本段及以上注释应
 *  予以保留,不得更改或删除原版权所有者姓名。二次开发者可以加注二次版权所有者,
 *  但应在遵守此协议的基础上,开放源代码、不得出售代码本身。
 *
 * 说明:本页代码基于Freescale官方示例代码修改,源代码文件为 mcg.c
 */
#include "common.h"
#include "HAL_MCG.h"

/*
 * LPLD_PLL_Setup
 * PLL初始化内核及其他系统时钟
 * 
 * 参数:
 *    clk_option--期望内核时钟频率
 *      |__PLLx--参见HAL_MCG.h中的PLL_option定义
 *
 * 输出:
 *    内核频率,单位MHz
 */
unsigned char LPLD_PLL_Setup(unsigned char pll_option)
{
  unsigned char pll_freq;
  unsigned char prdiv;
  
  if(pll_option<111)
  {
    prdiv = 24;  
  }
  else if(pll_option<201)
  {
    prdiv = 12; 
  }
  else if(pll_option<221)
  {
    prdiv = 11; 
  }
  else
  {
    return 0;
  }
  
  // 这里假设复位后 MCG 模块默认为 FEI 模式
  
  // 首先移动到 FBE 模式
  MCG_C2 = 0;
  
  // 振荡器初始化完成后,释放锁存状态下的 oscillator 和 GPIO 
  SIM_SCGC4 |= SIM_SCGC4_LLWU_MASK;
  LLWU_CS |= LLWU_CS_ACKISO_MASK;
  
  // 选择外部 oscilator 、参考分频器 and 清零 IREFS 启动外部osc
  // CLKS=2, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0
  MCG_C1 = MCG_C1_CLKS(2) | MCG_C1_FRDIV(3);  
  
  //while (!(MCG_S & MCG_S_OSCINIT_MASK)){};  // 等待 oscillator 初始化
  
  while (MCG_S & MCG_S_IREFST_MASK){}; // 等待参考时钟清零
  
  while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x2){}; // 等待时钟状态显示为外部参考时钟(ext ref clk)
  
  // 进入FBE模式
  // 配置 PLL 参考分频器, PLLCLKEN=0, PLLSTEN=0, PRDIV=5
  // 用晶振频率来选择 PRDIV 值. 仅在有频率晶振的时候支持
  // 产生 2MHz 的参考时钟给 PLL.
  MCG_C5 = MCG_C5_PRDIV(prdiv); // 设置 PLL 匹配晶振的参考分频数 
  
  // 确保MCG_C6处于复位状态,禁止LOLIE、PLL、和时钟控制器,清PLL VCO分频器
  MCG_C6 = 0x0;
  // 选择PLL VCO分频器,系统时钟分频器取决于时钟选项
  
  switch (pll_option) {
    case 60:
      // 设置系统选项分频
      // MCG=PLL, core = MCG, bus = MCG/2, FlexBus = MCG/2, Flash clock= MCG/3
      LPLD_Set_SYS_DIV(0,1,1,2);  //core=60M, bus=30M, FlexBus=30M, Flash Clk=20M
      // 设置 VCO 分频并使能 50MHz PLL, LOLIE=0, PLLS=1, CME=0, VDIV=1
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(6); //VDIV = 6 (2x30) 60MHz
      pll_freq = 60;
      break;
    case 70:
      LPLD_Set_SYS_DIV(0,1,1,2);  //core=70M, bus=35M, FlexBus=35M, Flash Clk=23.3M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(11); //VDIV = 11 (2x35) 70MHz
      pll_freq = 70;
      break;
    case 80:
      LPLD_Set_SYS_DIV(0,1,1,3);  //core=80M, bus=40M, FlexBus=40M, Flash Clk=20M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(16); //VDIV = 16 (2x40) 80MHz
      pll_freq = 80;
      break;
    case 90:
      LPLD_Set_SYS_DIV(0,1,1,3);  //core=90M, bus=45M, FlexBus=45M, Flash Clk=22.5M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(21); //VDIV = 21 (2x45) 90MHz
      pll_freq = 90;
      break;
    case 96:
      LPLD_Set_SYS_DIV(0,1,1,3);  //core=96M, bus=48M, FlexBus=48M, Flash Clk=22.5M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(24); //VDIV = 24 (2x48) 96MHz
      pll_freq = 96;
      break;
    case 100:
      LPLD_Set_SYS_DIV(0,1,1,3);  //core=100M, bus=50M, FlexBus=50M, Flash Clk=25M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(26); //VDIV = 26 (2x50) 100MHz
      pll_freq = 100;
      break;
    case 110:
      LPLD_Set_SYS_DIV(0,2,2,4);  //core=110M, bus=36.7M, FlexBus=36.7M, Flash Clk=22M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(31); //VDIV = 31 (2x55) 110MHz
      pll_freq = 110;
      break;
    case 120:
      LPLD_Set_SYS_DIV(0,2,2,4);  //core=120M, bus=40M, FlexBus=40M, Flash Clk=24M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(7); //VDIV = 7 (3.846x31) 119.2MHz
      pll_freq = 120;
      break;
    case 130:
      LPLD_Set_SYS_DIV(0,2,2,5);  //core=130M, bus=43M, FlexBus=43M, Flash Clk=21.6M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(10); //VDIV = 10 (3.846x34) 130.8MHz
      pll_freq = 130;
      break;
    case 150:
      LPLD_Set_SYS_DIV(0,2,2,5);  //core=150M, bus=50M, FlexBus=50M, Flash Clk=25M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(15); //VDIV = 15 (3.846x39) 150MHz
      pll_freq = 150;
      break;
    case 170:
      LPLD_Set_SYS_DIV(0,3,3,6);  //core=170M, bus=42.5M, FlexBus=42.5M, Flash Clk=24.3M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(20); //VDIV = 20 (3.846x44) 169.2MHz
      pll_freq = 170;
      break;
    case 180:
      LPLD_Set_SYS_DIV(0,3,3,7);  //core=180M, bus=45M, FlexBus=45M, Flash Clk=22.5M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(23); //VDIV = 23 (3.846x47) 180.8MHz
      pll_freq = 180;
      break;
    case 200:
      LPLD_Set_SYS_DIV(0,3,3,7);  //core=200M, bus=50M, FlexBus=50M, Flash Clk=25M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(28); //VDIV = 28 (3.846x52) 200MHz
      pll_freq = 200;
      break;
    case 209:
      LPLD_Set_SYS_DIV(0,4,4,8);  //core=209M, bus=42M, FlexBus=42M, Flash Clk=23.2M
      MCG_C6 = MCG_C6_PLLS_MASK | MCG_C6_VDIV(26); //VDIV = 26 (4.17x50) 208.5MHz
      pll_freq = 209;
    break;
  }
  
  while (!(MCG_S & MCG_S_PLLST_MASK)){}; // wait for PLL status bit to set
  
  while (!(MCG_S & MCG_S_LOCK_MASK)){}; // Wait for LOCK bit to set
  
  // 已经进入PBE模式
  
  // Transition into PEE by setting CLKS to 0
  // CLKS=0, FRDIV=3, IREFS=0, IRCLKEN=0, IREFSTEN=0
  MCG_C1 &= ~MCG_C1_CLKS_MASK;
  
  // Wait for clock status bits to update
  while (((MCG_S & MCG_S_CLKST_MASK) >> MCG_S_CLKST_SHIFT) != 0x3){};
  
  // 已经进入PEE模式
  
  return pll_freq;
} 


/*
 * LPLD_Set_SYS_DIV
 * 设置系统始终分频(FSCL官方代码)
 *
 * 说明:
 * 这段代码必须放置在RAM中. It is a workaround for errata e2448.
 * 当Flash时钟分频改变的时候,Flash预读取必须禁用.
 * 当正在从Flash执行的时候这里不能执行.
 * 在预读取被重新使能之前必须在时钟分频改变后有一段小的延时.
 *
 * 参数:
 *    outdiv1~outdiv4--分别为core, bus, FlexBus, Flash时钟分频系数
 */
#if (defined(IAR))
	__ramfunc void LPLD_Set_SYS_DIV(uint32 outdiv1, uint32 outdiv2, uint32 outdiv3, uint32 outdiv4)
#elif (defined(CW))
__relocate_code__ 
void LPLD_Set_SYS_DIV(uint32 outdiv1, uint32 outdiv2, uint32 outdiv3, uint32 outdiv4)
#endif
{
  uint32 temp_reg;
  uint8 i;
  
  temp_reg = FMC_PFAPR; // 备份 FMC_PFAPR 寄存器
  
  // 设置 M0PFD 到 M7PFD 为 1 禁用预先读取
  FMC_PFAPR |= FMC_PFAPR_M7PFD_MASK | FMC_PFAPR_M6PFD_MASK | FMC_PFAPR_M5PFD_MASK
             | FMC_PFAPR_M4PFD_MASK | FMC_PFAPR_M3PFD_MASK | FMC_PFAPR_M2PFD_MASK
             | FMC_PFAPR_M1PFD_MASK | FMC_PFAPR_M0PFD_MASK;
  
  // 设置时钟分频为期望值  
  SIM_CLKDIV1 = SIM_CLKDIV1_OUTDIV1(outdiv1) | SIM_CLKDIV1_OUTDIV2(outdiv2) 
              | SIM_CLKDIV1_OUTDIV3(outdiv3) | SIM_CLKDIV1_OUTDIV4(outdiv4);

  // 延时一小段时间等待改变
  for (i = 0 ; i < outdiv4 ; i++)
  {}
  
  FMC_PFAPR = temp_reg; // 回复原先的 FMC_PFAPR 寄存器值
  
  return;
} // set_sys_dividers

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -