19160|16

603

帖子

1

TA的资源

纯净的硅(中级)

楼主
 

Atmel SAM D21开发板试用心得 ——利用Keil5,全速运行 [复制链接]

 
本帖最后由 sjtitr 于 2014-10-10 00:18 编辑

不知怎的,一提到全速运行,楼主第一想起来的是泰坦尼克号……

于是在这个问题上,楼主撞了冰山。所幸最后解决了,那我们来分享一下这一过程。

通常楼主拿到一块板子,首先是让它火力全开,全速运行——很多时候还是执行得快一点比较好。
值得一提的是,楼主是个Keil控,PC里常年安装的只有这个IDE,理由嘛……比较和谐。
对于SamD21来说,到处都能看到:
  • 基于 ARM Cortex-M0+ 的 MCU 的工作频率高达 48MHz

那么好,就让它来跑个48MHz!所以先学习时钟系统。

SamD21的时钟系统框图十分清晰:

再加上根据多处描述,得知我们需要开启DFLL48M,那么目标就明确了。

如果是使用Atmel的官方IDE,AtmelStudio,也许搞出个Example还很容易的,可是楼主使用的是Keil,所以就会麻烦一些,参考相关手册:
Atmel-42119-SAM-D20-D21-System-Clock-Management-Driver-SYSTEM-CLOCK_Application-Note_AT03259
我们一样可以把这个东东设置好的,对吧。

首先,了解到上电以后,系统时钟大概是这样的:


也就是说,这个时候的系统时钟是1MHz,所以我们来写段代码:
  1. #include "samd21.h"

  2. void LED_Init(void)
  3. {
  4.         PORT->Group[1].DIRSET.reg = PORT_PB30;
  5.         PORT->Group[1].OUTSET.reg = PORT_PB30;
  6. }
  7. void LED_ON(void)
  8. {
  9.         PORT->Group[1].OUTCLR.reg = PORT_PB30;
  10. }
  11. void LED_OFF(void)
  12. {
  13.         PORT->Group[1].OUTSET.reg = PORT_PB30;
  14. }

  15. void SysTick_Handler(void)
  16. {
  17.         if(PORT->Group[1].OUTSET.reg == PORT_PB30)
  18.         {
  19.                 LED_ON();
  20.         }
  21.         else
  22.         {
  23.                 LED_OFF();
  24.         }
  25. }

  26. int main(void)
  27. {
  28.         LED_Init();
  29.         SysTick_Config(1000000);
  30.         while(1)
  31.         {
  32.         }
  33. }
复制代码

注意代码参考了https://bbs.eeworld.com.cn/forum. ... 47420&highlight=d21
关于如何在Keil下进行SamD21开发,也可以参考这篇文章。
所以上面这段代码的作用就是让LED每一秒种变一次,结果就是以2s为周期在闪烁了。


经过运行确认,效果没有错。

接下来自然就是开启DFLL48M,需要参考GCLK:
需要利用Generic Clock Generator 0来产生系统时钟,

而根据对System Controller部分的学习:

得知还需要在SystemController中设置DFLL48M作为Generic Clock Generator 0 的时钟源,它有两种模式(Open和Close,开环和闭环控制)
我们这次参考前文提到的文档,设置DFLL48M为Open模式。

根据手册学习了Open模式,于是又知道要去取NVM Software Calibration Area中关于DFLL48M设置的两个值。


于是综上所述,我们可以开动全速了。
也就是这些东西,把楼主推上了冰山——楼主忙乱之中漏设了一个位。
简单介绍一下楼主遇到的问题,便于后来人参考——设置的过程很顺利,主时钟被设置成了DFLL48M……可是这个玩意的使能位的设置,却被漏掉了,再加上文档的干扰,不知道最后产生了个什么鬼程序,当把程序下载到芯片中,噩梦开始了,(芯片立即不能运行了)整个芯片处于瘫痪状态,用Keil连接调试或者尝试重新下载程序,都会弹出提示框—— Cannot enter Debug Mode:


除了仿真器设置不正确,那就是芯片进入“分歧者”模式了……之前使用别的芯片遇到过这样的情况,某种角度讲也是正常,在没有合理设置好唤醒的时候一上电就进入休眠模式、或者开机状态设错了等等……通常解决方案就是,可以选择其他的Boot模式,进行芯片擦除,或者的话,利用NMI中断,如果没有实现NMI中断处理,就多次实践正确在Reset之后立即进入NMI中断的死循环或者异常中,楼主曾经利用示波器的方波进行这个操作,也取得过成功。

检查一下芯片手册……和谐,没有Boot模式选择……又和谐,NMI默认是关闭的,那叫什么NMI!
当时楼主也慌了……还没写心得呢就废了?……额

遇到这样的问题不要急着慌张,不要忘了,我们现在用的不是官方的工具,而是第三方环境,所以赶紧下载AtmelStudio

在AtmelStudio上随便建立一个Example,然后进行相关硬件设置,最后下载程序,终于可以擦掉原来的程序写入新程序了。
再回到Keil上,一切恢复正常。
当然了,也不要着急训斥Keil的不力,因为毕竟同样是下载,可能只是楼主没有掌握在Keil下更高端的下载设置而已(Keil可以自己设置下载命令的)
其实楼主可能更会去吐槽Sam大叔的复杂的时钟设置……呵呵,当然了,这其实也是灵活的时钟设置。

总之问题是解决了,这样就成了很有用的经验了,如果你也遇到这种情况,作为参考,看看能否提供什么帮助或者思路。

OK。关于冰山的问题解释过了,最后就是分享楼主经过尝试,成功全速运行的成果。

首先,默认被8分频的OSC8M,把它恢复成不分频——
  1. void configure_osc8m(SYSCTRL_OSC8M_Type osc8m)
  2. {
  3.         osc8m.bit.ENABLE = 1;
  4.         SYSCTRL->OSC8M = osc8m;
  5. }

  6. void configure_osc8m_8m(void)
  7. {
  8.         SYSCTRL_OSC8M_Type osc8m;
  9.         
  10.         osc8m = SYSCTRL->OSC8M;
  11.         
  12.         osc8m.bit.PRESC = SYSCTRL_OSC8M_PRESC_0_Val;
  13.         osc8m.bit.RUNSTDBY = 0;
  14.         osc8m.bit.ONDEMAND = 1;
  15.         
  16.         configure_osc8m(osc8m);
  17. }
复制代码

接下来设置DFLL48M
  1. void configure_dfll(SYSCTRL_DFLLCTRL_Type dfllctrl, SYSCTRL_DFLLMUL_Type dfllmul, SYSCTRL_DFLLVAL_Type dfllval)
  2. {
  3.         SYSCTRL->DFLLCTRL.reg = dfllctrl.reg & ~SYSCTRL_DFLLCTRL_ONDEMAND;
  4.         
  5.         while (!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_DFLLRDY)) {
  6.                 /* Wait for DFLL sync */
  7.         }

  8.         SYSCTRL->DFLLMUL.reg         = dfllmul.reg;
  9.         SYSCTRL->DFLLVAL.reg         = dfllval.reg;
  10.         
  11.         dfllctrl.bit.ENABLE = 1;

  12.         /* Write full configuration to DFLL control register */
  13.         SYSCTRL->DFLLCTRL.reg = dfllctrl.reg;
  14. }

  15. void configure_dfll_open_loop(void)
  16. {
  17.         SYSCTRL_DFLLCTRL_Type dfllctrl;
  18.         SYSCTRL_DFLLMUL_Type dfllmul;
  19.         SYSCTRL_DFLLVAL_Type dfllval;
  20.         
  21.         dfllctrl.bit.LLAW                 = 0;
  22.         dfllctrl.bit.STABLE         = 0;
  23.         dfllctrl.bit.QLDIS                 = 0;
  24.         dfllctrl.bit.CCDIS                 = 0;
  25.         dfllctrl.bit.ONDEMAND = 1;
  26.         
  27.         dfllctrl.bit.MODE                 = 0;
  28.         
  29.         dfllval.bit.COARSE                 = (*((uint8_t*)(0x806020+7)))>>2;//0x1f / 4; /* Midpoint */
  30.         dfllval.bit.FINE                         = (*((uint32_t*)(0x806020+8))) & 0x3FF;//0xff / 4; /* Midpoint */
  31.         
  32.         dfllmul.bit.CSTEP                 = 1;
  33.         dfllmul.bit.FSTEP                 = 1;
  34.         dfllmul.bit.MUL                         = 6; /* Multiply 8MHz by 6 to get 48MHz */        
  35.         
  36.         configure_dfll(dfllctrl, dfllmul, dfllval);
  37.         
  38.         NVMCTRL->CTRLB.bit.RWS = 2;
  39. }
复制代码
其中关于 COARSE 和 FINE 的设置,不要忘记了是从NVM Software Calibration Area中取得的,这样才准确。

然后,开启高速主时钟——
  1. void configure_gclk(GCLK_GENCTRL_Type genctrl, GCLK_GENDIV_Type gendiv)
  2. {
  3.         while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {
  4.                 /* Wait for synchronization */
  5.         };

  6.         //cpu_irq_enter_critical();

  7.         /* Select the correct generator */
  8.         GCLK->GENDIV.bit.ID = gendiv.bit.ID;

  9.         /* Write the new generator configuration */
  10.         while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {
  11.                 /* Wait for synchronization */
  12.         };
  13.         GCLK->GENDIV  = gendiv;

  14.         while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {
  15.                 /* Wait for synchronization */
  16.         };
  17.         genctrl.bit.GENEN = GCLK->GENCTRL.bit.GENEN;
  18.         GCLK->GENCTRL = genctrl;

  19.         //cpu_irq_leave_critical();
  20. }


  21. void configure_gclk_gen_dfll(void)
  22. {
  23.         /* Change system clock to DFLL */        
  24.         GCLK_GENCTRL_Type genctrl;
  25.         GCLK_GENDIV_Type gendiv;
  26.         
  27.         genctrl.reg = 0;
  28.         gendiv.reg = 0;

  29.         genctrl.bit.ID = GCLK_CLKCTRL_GEN_GCLK0_Val;
  30.         gendiv.bit.ID = GCLK_CLKCTRL_GEN_GCLK0_Val;
  31.         
  32.         genctrl.bit.SRC = GCLK_SOURCE_DFLL48M;
  33.         genctrl.bit.DIVSEL = 0;
  34.         genctrl.bit.IDC = 0;
  35.         genctrl.bit.OOV = 0;
  36.         genctrl.bit.RUNSTDBY = 0;
  37.         genctrl.bit.OE = 0;
  38.         
  39.         gendiv.bit.DIV = 0;
  40.         
  41.         configure_gclk(genctrl, gendiv);
  42. }
复制代码

最后,要在main函数中启用上面这些——
  1. int ieo=0;
  2. int main(void)
  3. {
  4.         while(ieo!=5);
  5.         configure_osc8m_8m();
  6.         configure_dfll_open_loop();
  7.         configure_gclk_gen_dfll();
  8.         LED_Init();
  9.         SysTick_Config(48000000/4);
  10.         while(1)
  11.         {
  12.         }
  13. }
复制代码
稍微解释一下楼主的ieo变量,楼主也是害怕了,找来个变量挡一下,
调试的时候,直接修改变量在内存中的值,或者干脆改变程序运行位置,调试后面的内容。
一直到时钟系统调试成功了才可以把它去掉,免得芯片再一次暴走。
最后设置的SysTick_Config是CM内核通用的,里面的时间设成了1/4秒变一次,也就是每秒闪两次……不能再慢了,1/2的话,好像Tick寄存器装不下,就不正常了,具体的楼主并没有查找资料,只是设上就不正确了,于是楼主改回1/4了,记忆中Tick周期是有位数限制的,不是32位。



最后附上楼主的源码——main.c
main.zip (1.18 KB, 下载次数: 199)



此帖出自单片机论坛

最新回复

很好的东西不错啊非常喜欢再接再砺发表更加多的额东西,希望做得更加好新年快乐万事如意   详情 回复 发表于 2023-1-21 11:09
点赞 关注(1)
 

回复
举报

262

帖子

4

TA的资源

一粒金砂(高级)

沙发
 
借鉴、学习,感谢、分享
此帖出自单片机论坛
 
 

回复

41

帖子

1

TA的资源

一粒金砂(中级)

板凳
 
开始入门
此帖出自单片机论坛
 
 
 

回复

79

帖子

1

TA的资源

一粒金砂(中级)

4
 
不错不错 学习了!
此帖出自单片机论坛
 
 
 

回复

17

帖子

0

TA的资源

一粒金砂(中级)

5
 
楼主,你使用的osc8M,如果使用外部晶振32K的,我看到例程里
int main(void)
{
//! [main]
        /* Configure the external 32KHz oscillator */
//! [config_extosc32k_main]
        configure_extosc32k();//配置32K的外部晶振
//! [config_extosc32k_main]

        /* Enable the external 32KHz oscillator */
//! [enable_extosc32k_main]
        enum status_code osc32k_status =
                        system_clock_source_enable(SYSTEM_CLOCK_SOURCE_XOSC32K);//使能32K的外部晶振

        if (osc32k_status != STATUS_OK) {
                /* Error enabling the clock source */
        }
//! [enable_extosc32k_main]

        /* Configure the DFLL in open loop mode using default values */
//! [config_dfll_main]
        configure_dfll_open_loop();//使用默认值来配置数字锁相环为开环模式
//! [config_dfll_main]

        /* Enable the DFLL oscillator */
//! [enable_dfll_main]
        enum status_code dfll_status =
                        system_clock_source_enable(SYSTEM_CLOCK_SOURCE_DFLL);//使能数字锁相环

        if (dfll_status != STATUS_OK) {
                /* Error enabling the clock source */
        }
//! [enable_dfll_main]

        /* Configure flash wait states before switching to high frequency clock */
//! [set_sys_wait_states]
        system_flash_set_waitstates(2);//转换为高频时钟之前配置Flash为等待状态
//! [set_sys_wait_states]

        /* Change system clock to DFLL *///将系统时钟转换为数字锁相环时钟
//! [set_sys_clk_src]
        struct system_gclk_gen_config config_gclock_gen;
        system_gclk_gen_get_config_defaults(&config_gclock_gen);
        config_gclock_gen.source_clock    = SYSTEM_CLOCK_SOURCE_DFLL;
        config_gclock_gen.division_factor = 1;
        system_gclk_gen_set_config(GCLK_GENERATOR_0, &config_gclock_gen);
//! [set_sys_clk_src]
//! [main]

        while (true) {

        }
}

但是始终找不到配置晶振的IO设置
此帖出自单片机论坛

点评

这个问题,首先我没怎么研究32K晶振的事,所以我现在也不能确定帮不帮的了你。 我在手册上看到,关于Port口的功能设定里面,没有关于晶振的功能,然后在关于32K晶振的描述里面,发现这样一段话: 根据这个我分析  详情 回复 发表于 2015-1-14 09:23
 
 
 

回复

603

帖子

1

TA的资源

纯净的硅(中级)

6
 
biniancishi 发表于 2015-1-13 10:31
楼主,你使用的osc8M,如果使用外部晶振32K的,我看到例程里
int main(void)
{
  ...
}

但是始终找不到配置晶振的IO设置[/quote]
这个问题,首先我没怎么研究32K晶振的事,所以我现在也不能确定帮不帮的了你。
我在手册上看到,关于Port口的功能设定里面,没有关于晶振的功能,然后在关于32K晶振的描述里面,发现这样一段话:
[quote]At power-on reset (POR) the XOSC32K is disabled, and the XIN32/XOUT32 pins can be used as General Purpose I/O
(GPIO) pins or by other peripherals in the system. When XOSC32K is enabled, the operating mode determines the GPIO
usage. When in crystal oscillator mode, XIN32 and XOUT32 are controlled by the SYSCTRL, and GPIO functions are
overridden on both pins. When in external clock mode, only the XIN32 pin will be overridden and controlled by the
SYSCTRL, while the XOUT32 pin can still be used as a GPIO pin.
根据这个我分析,晶振功能可能是不需要设定GPIO的,一旦设定开启晶振,端口会自动被用于晶振,而无视你关于GPIO的设定。
仅仅是推测,你还是应当试验一下。



此帖出自单片机论坛
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

7
 
非常好,不知道还有没有其他的例程?
此帖出自单片机论坛
 
个人签名Ming
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

8
 
楼主,请问keil调试samd21的开发板,debug选项里面选择哪个下载线啊。没有开发板自带的edbg下载线啊,怎么下载程序和调试呢。
此帖出自单片机论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

9
 
mycent 发表于 2015-10-5 12:26
楼主,请问keil调试samd21的开发板,debug选项里面选择哪个下载线啊。没有开发板自带的edbg下载线啊,怎么 ...

我找到了,由于SAM R21 Xplained Pro Kit的EDBG调试接口支持的是DAP调试协议。因此在option-->Debug-->Use: CMSIS-DAP Debugger,并在其后的Settings里面确定识别出EDBG。
https://bbs.eeworld.com.cn/thread-454110-1-1.html
此帖出自单片机论坛
 
 
 

回复

603

帖子

1

TA的资源

纯净的硅(中级)

10
 
mycent 发表于 2015-10-5 12:40
我找到了,由于SAM R21 Xplained Pro Kit的EDBG调试接口支持的是DAP调试协议。因此在option-->Debug-->Us ...

此帖出自单片机论坛
 
 
 

回复

3

帖子

0

TA的资源

一粒金砂(中级)

11
 

哥们在的啊。交流下啊!我想把asf弄到keil下。目前看来比较麻烦。
加个QQ交流下keil下玩samd21.
qq:6859620
此帖出自单片机论坛
 
 
 

回复

2

帖子

0

TA的资源

一粒金砂(初级)

12
 
本帖最后由 zhang0352505 于 2017-1-6 14:22 编辑

楼主请教一下,
在设置DFLL时钟源的时候,实际上只能设置成GCLK的的0~7,在楼主的例程中没有看到设置该时钟。
并且该时钟我在ATmel Start中设置时,是不能大于33kHz的,所以不知道您怎么弄成8M Hz的。

此帖出自单片机论坛
 
 
 

回复

3

帖子

0

TA的资源

禁止发言

13
 
重新开始玩这个芯片,入门比较晚,来向楼主学习。
此帖出自单片机论坛
 
 
 

回复

13

帖子

0

TA的资源

一粒金砂(中级)

14
 
您好,我司是microchip,atmel一级代理商,您的问题我司有专门的FAE帮解决,有需要可联系,13798245017
此帖出自单片机论坛
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(中级)

15
 
很好的东西不错啊非常喜欢再接再砺
此帖出自单片机论坛
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(中级)

16
 

很好的东西不错啊非常喜欢再接再砺发表更加多的额东西,希望做得更加好新年快乐万事如意

此帖出自单片机论坛
 
 
 

回复

4

帖子

0

TA的资源

一粒金砂(中级)

17
 

很好的东西不错啊非常喜欢再接再砺发表更加多的额东西,希望做得更加好新年快乐万事如意

此帖出自单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表