IDLE模式和 UART的疑问

[复制链接]
5723|20
 楼主| David_ming 发表于 2010-10-21 16:34 | 显示全部楼层 |阅读模式
本帖最后由 David_ming 于 2010-10-27 20:49 编辑

碰到问两个问题:

1. M0的timer和cpu的时钟都是用外部12M的时候,如果关掉内部的22M,进IDLE模式不能唤醒,打开22M后才可以正常工作。
2. M0的UART和CPU的时钟都是外部12M的时候,如果关闭内部的22M,会printf不出来数据,打开22M后可以正常工作。

这是软件的bug还是硬件就这样做的??3Q。

备注,我的UART的时钟源的确有进行切换动作  SYSCLK->CLKSEL1.UART_S = 0
 楼主| David_ming 发表于 2010-10-21 16:48 | 显示全部楼层
单独跑timer也不成,IP的clock都需要22M的支持??
X-Hawk 发表于 2010-10-21 17:27 | 显示全部楼层
22M不是必须。
这个可能要结合代码看才能界定问题。楼主方便秀一下代码?
yybj 发表于 2010-10-21 18:20 | 显示全部楼层
把代码贴出来看一下吧
 楼主| David_ming 发表于 2010-10-21 20:35 | 显示全部楼层
代码很简单,就在芯唐的demo里面的UNLOCKREG()后面加两句
  1. SYSCLK->CLKSEL0.HCLK_S = 0;
  2. SYSCLK->PWRCON.OSC22M_EN = 0;

明天早上我上最精简化可以直接编译的代码
X-Hawk 发表于 2010-10-21 20:39 | 显示全部楼层
CLKSEL1.UART_S 的设定,选用哪个clock当UART的clock呢?
如果关掉了22M, 又拿22M给UART用的话。。。。
金鱼木鱼 发表于 2010-10-21 23:00 | 显示全部楼层
看看数据手册上有没有说的
 楼主| David_ming 发表于 2010-10-22 09:30 | 显示全部楼层
本帖最后由 David_ming 于 2010-10-22 09:36 编辑

/*---------------------------------------------------------------------------------------------------------*/
/*                                                                                                         */
/* Copyright(c) 2009 Nuvoton Technology Corp. All rights reserved.                                         */
/*                                                                                                         */
/*---------------------------------------------------------------------------------------------------------*/
#include <stdio.h>
#include "NUC1xx.h"
#include "Driver/DrvUART.h"
#include "Driver/DrvRTC.h"
#include "Driver/DrvGPIO.h"
#include "Driver/DrvSYS.h"
/*---------------------------------------------------------------------------------------------------------*/
/* Global variables                                                                                        */
/*---------------------------------------------------------------------------------------------------------*/
volatile uint32_t  g_u32TICK = FALSE;
volatile int32_t   g_bAlarm  = FALSE;

/*---------------------------------------------------------------------------------------------------------*/
/* RTC Tick Callback function                                                                              */
/*---------------------------------------------------------------------------------------------------------*/
void DrvRTC_TickISR(void)
{
S_DRVRTC_TIME_DATA_T sCurTime;

/* Get the currnet time */
DrvRTC_Read(DRVRTC_CURRENT_TIME, &sCurTime);  

printf("Current Time:%d/%02d/%02d %02d:%02d:%02d\n",sCurTime.u32Year,sCurTime.u32cMonth,sCurTime.u32cDay,sCurTime.u32cHour,sCurTime.u32cMinute,sCurTime.u32cSecond);   

g_u32TICK++;
}


/*---------------------------------------------------------------------------------------------------------*/
/* RTC Alarm Callback function                                                                             */
/*---------------------------------------------------------------------------------------------------------*/
void DrvRTC_AlarmISR(void)
{

printf("Alarm!!\n");

g_bAlarm = TRUE;
}

static void TestItem (void)
{
    printf("\n\n");
    printf("+-----------------------------------------------------------+\n");
    printf("|                    RTC Sample Program                     |\n");
    printf("+-----------------------------------------------------------+\n");
    printf("| [0] Time Display Test                                     | \n");
    printf("| [1] Alarm Test                                            | \n");
    printf("+-----------------------------------------------------------+\n");
    printf("| [2] Quit                                                  |\n");
    printf("+-----------------------------------------------------------+\n");
    printf("Select key : \n");
}

void SysTimerDelay(uint32_t us)
{
    SysTick->LOAD = us * 22; /* Assume the internal 22MHz RC used */
    SysTick->VAL   =  (0x00);
    SysTick->CTRL = (1 << SYSTICK_CLKSOURCE) | (1<<SYSTICK_ENABLE);
    /* Waiting for down-count to zero */
    while((SysTick->CTRL & (1 << 16)) == 0);
}

/*---------------------------------------------------------------------------------------------------------*/
/* RTC Test Sample                                                                                */
/* Test Item                                                                                */
/*  1. Time Display Test                       */
/*    Use RTC Tick interrupt to display time every one second.                              */
/*  2. Alarm Test                         */
/*     Get the current and alarm after 10 seconds                 */
/*---------------------------------------------------------------------------------------------------------*/
int32_t main()           
{
unsigned int i;
S_DRVRTC_TIME_DATA_T sInitTime;
int32_t bLoop = TRUE;
uint8_t u8Item;

STR_UART_T sParam;

UNLOCKREG();
    SYSCLK->PWRCON.XTL12M_EN = 1;



for(i = 0; i < 0xffff; i++);
SYSCLK->CLKSEL0.HCLK_S = 0;
SYSCLK->PWRCON.OSC22M_EN = 0; //有这句就完蛋了






   /* Waiting for Xtal stalble */
    SysTimerDelay(5000);
/* UART Setting */
    sParam.u32BaudRate = 115200;
    sParam.u8cDataBits = DRVUART_DATABITS_8;
    sParam.u8cStopBits = DRVUART_STOPBITS_1;
    sParam.u8cParity   = DRVUART_PARITY_NONE;
    sParam.u8cRxTriggerLevel = DRVUART_FIFO_1BYTES;
/* Set UART Pin */
DrvGPIO_InitFunction(FUNC_UART0);
/* Set UART Configuration */
if(DrvUART_Open(UART_PORT0,&sParam) == E_SUCCESS)
{  
  /* RTC Initialize */
  DrvRTC_Init();
  
  /* Time Setting */
  sInitTime.u32Year   = 2009;
  sInitTime.u32cMonth  = 1;
  sInitTime.u32cDay   = 19;
  sInitTime.u32cHour   = 13;
  sInitTime.u32cMinute  = 20;
  sInitTime.u32cSecond  = 0;
  sInitTime.u32cDayOfWeek = DRVRTC_MONDAY;
  sInitTime.u8cClockDisplay = DRVRTC_CLOCK_24;   
  /* Initialization the RTC timer */
  if(DrvRTC_Open(&sInitTime) !=E_SUCCESS)
  {
   printf("RTC Open Fail!!\n");
   return FALSE;
  }  
  
  while(bLoop)
  {
   TestItem();
   u8Item = getchar();
   
   switch(u8Item)
   {
    case '0':
    {
     S_DRVRTC_TICK_T sTick;
     
     printf("\n0. RTC Time Display Test (Exit after 5 seconds)\n");
      
     /* Set Tick property */
     sTick.ucMode = DRVRTC_TICK_1_SEC;
     sTick.pfnTickCallBack = DrvRTC_TickISR;  
     
     /* Set Tick setting */
     DrvRTC_Ioctl(0,DRVRTC_IOC_SET_TICK_MODE, (uint32_t)&sTick,0);
     /* Enable RTC Tick Interrupt and install tick call back function */
     DrvRTC_Ioctl(0,DRVRTC_IOC_ENABLE_INT, (uint32_t)DRVRTC_TICK_INT,0);
     g_u32TICK = 0;
   
     NVIC_EnableIRQ(RTC_IRQn);
     while(g_u32TICK < 5);
     /* Disable RTC Tick Interrupt */
     DrvRTC_Ioctl(0,DRVRTC_IOC_DISABLE_INT, (uint32_t)DRVRTC_TICK_INT,0);      
     break;
    }
    case '1':
    {
     S_DRVRTC_TIME_DATA_T sCurTime;
     
     printf("\n1. DrvRTC Alarm Test (Alarm after 10 seconds)\n");
      
     g_bAlarm = FALSE;
   
     /* Get the currnet time */
     DrvRTC_Read(DRVRTC_CURRENT_TIME, &sCurTime);
   
     /* Set Alarm call back function */
     sCurTime.pfnAlarmCallBack = DrvRTC_AlarmISR;
     printf("Current Time:%d/%02d/%02d %02d:%02d:%02d\n",sCurTime.u32Year,sCurTime.u32cMonth,sCurTime.u32cDay,sCurTime.u32cHour,sCurTime.u32cMinute,sCurTime.u32cSecond);
     
     /* The alarm time setting */
     sCurTime.u32cSecond = sCurTime.u32cSecond + 10;  
     
     /* Set the alarm time (Install the call back function and enable the alarm interrupt)*/
     DrvRTC_Write(DRVRTC_ALARM_TIME,&sCurTime);
      
     NVIC_EnableIRQ(RTC_IRQn);
     
     while(!g_bAlarm);
     
     printf("Current Time:%d/%02d/%02d %02d:%02d:%02d\n",sCurTime.u32Year,sCurTime.u32cMonth,sCurTime.u32cDay,sCurTime.u32cHour,sCurTime.u32cMinute,sCurTime.u32cSecond);
        
     break;   
    }
    case '2':
     bLoop = FALSE;
     break;
    default:
     printf("Wrong Item\n");
     break;   
   }
   
  }
  
  /* Disable RTC Clock */  
  DrvRTC_Close();
  
  /* Disable UART Clock */
  DrvUART_Close(UART_PORT0);
  
  return TRUE;
}
else
  return FALSE;
}
 楼主| David_ming 发表于 2010-10-22 09:33 | 显示全部楼层
本帖最后由 David_ming 于 2010-10-22 09:34 编辑

上面一段是官方的RTC demo,其它的地方我没动,只是加上了中间那点,不知道是哪里出了问题:(
X-Hawk 发表于 2010-10-22 09:48 | 显示全部楼层
嗯,确定问题就是改了系统 clock, 没有告诉UART要用另外的clock,
请参考6楼
 楼主| David_ming 发表于 2010-10-22 09:54 | 显示全部楼层
我原来试过,加上也不行

        UNLOCKREG();
    SYSCLK->PWRCON.XTL12M_EN = 1;
        for(i = 0; i < 0xffff; i++);
        SYSCLK->CLKSEL0.HCLK_S = 0;
        __nop();
        __nop();
        SYSCLK->PWRCON.OSC22M_EN = 0;
        SYSCLK->CLKSEL1.UART_S = 0;
静默 发表于 2010-10-22 09:55 | 显示全部楼层
6楼是正解.....
   UNLOCKREG();
   SYSCLK->PWRCON.XTL12M_EN = 0;
   SYSCLK->CLKSEL1.UART_S = 0x03;
 楼主| David_ming 发表于 2010-10-22 09:57 | 显示全部楼层
各位大仙们能否也试试,我试了确实不行呀:(
 楼主| David_ming 发表于 2010-10-22 19:59 | 显示全部楼层
似乎BOD也需要内震10K的支持。。。。
 楼主| David_ming 发表于 2010-10-27 20:46 | 显示全部楼层
楼主把我的帖子删了吧,问了也白问:(
行不改名 发表于 2010-10-28 00:18 | 显示全部楼层
楼主不要太泄气了.如有人试过一定会说的,我改天试一下.
X-Hawk 发表于 2010-10-28 13:46 | 显示全部楼层
我试了一下,完全可以的。
楼主的SysTimerDelay的实现,依赖于SysTick,
SysTick要运行依赖于一个时钟。。。。就是22M, 然而楼主把22M关了。
所以加了一句将SysTick切换到12M的代码。

  1. int32_t main()           
  2. {
  3.         unsigned int i;
  4.         S_DRVRTC_TIME_DATA_T sInitTime;
  5.         int32_t bLoop = TRUE;
  6.         uint8_t u8Item;

  7.         STR_UART_T sParam;

  8.         UNLOCKREG();
  9.     SYSCLK->PWRCON.XTL12M_EN = 1;
  10.        
  11.         for(i = 0; i < 0xffff; i++);
  12.         SYSCLK->CLKSEL0.HCLK_S = 0;
  13.         SYSCLK->CLKSEL0.STCLK_S = 0;
  14.         SYSCLK->CLKSEL1.UART_S = 0;

  15.         SYSCLK->PWRCON.OSC22M_EN = 0; //有这句也不会完蛋了

  16.         /* Waiting for Xtal stalble */
  17.     SysTimerDelay(5000);
  18.         /* UART Setting */
  19.     sParam.u32BaudRate = 115200;
  20.     sParam.u8cDataBits = DRVUART_DATABITS_8;
  21.     sParam.u8cStopBits = DRVUART_STOPBITS_1;
  22.     sParam.u8cParity   = DRVUART_PARITY_NONE;
  23.     sParam.u8cRxTriggerLevel = DRVUART_FIFO_1BYTES;
  24.         /* Set UART Pin */
  25.         DrvGPIO_InitFunction(E_FUNC_UART0);
  26.         /* Set UART Configuration */
  27.         if(DrvUART_Open(UART_PORT0,&sParam) == E_SUCCESS)
  28.         {  
  29.                 printf("DrvUART_Open OK!!\n");
  30.         }
  31.         while(1);
  32. }
金鱼木鱼 发表于 2010-10-29 18:30 | 显示全部楼层
学习了,我也试下
 楼主| David_ming 发表于 2010-10-30 12:04 | 显示全部楼层
多谢斑竹的提醒,经过“无数”次的折腾,问题确定了------即:切换UART的时钟源操作一定要在关闭22M内震之前完成,即使是已经将HCLK切换到12M外震而且外震已经稳定。
即时生效 发表于 2010-10-30 17:11 | 显示全部楼层
哦,学习了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名::“哥洒脱如此”

22

主题

762

帖子

2

粉丝
快速回复 在线客服 返回列表 返回顶部
0