FlexBus
Kinetis
Kinetis
FlexBus
Kinetis 系统开发(十一)之 FlexBus
【原创】从零入手 Kinetis
FlexBus 模块
•
2012-06-20 14:31 发表
系统分类:嵌入式系统
自定义分类:Kinetis
• 标签:Kinetis K60 FlexBus
呼... ...终于腾出时间更新下博客了,真是好些日子没写了,终于又回归了。期间几个网友都在问
我什么时候更新,哎,有点惭愧,直到今天才更新出来,这几天爆发一下,补补更,嘿嘿(小说体的
感觉又来了,有木有)。这些天感觉还没到盛夏,天气就热的发闷,别的地儿不知道,济南是热成火
炉似的了,所以冬暖夏凉的实验室是个好去处,所以说主观上我是不想宅的,但是客观因素让我不得
不宅在实验室了,呵呵,那就捋胳膊抹袖子开始整吧(咳咳,喝口水先)~
从零系列的第十一篇(呵呵,不经意间已经写了十篇了)——FlexBus 应用, 在上一系列就已
经预报了,结果拖到现在,让一些等着的博友等了这么久,惭愧惭愧,以后应承下来的就尽量早点搞
完,越拖越写不动,真的体会到这种感觉。其实前一周一边在准备众星捧月的比赛,一边在写 Kinetis
的 USB 底层驱动,一直到前天才开始准备写该篇了,本来是想着趁热打铁的把 USB 模块介绍出来的,
不过还是决定先把这篇补上再说,后续篇章会写出来 Kinetis 的 USB 模块(由于 USB 内容较庞大,
我整整搞了一周,所以打算分成几篇写出来,有用到的敬请期待,呵呵,这次不会太久),希望不会
让大家失望才好,哈哈。
FlexBus 模块,我早在今年年前就写好了并作为开发框架代码的一部分一块上传到了飞思卡尔创
意嘉年华小组里了,后来又写了篇 FlexBus 外扩 SRAM 的硬件篇,本来作为核心的软件篇早就该写
出来了,结果难产到现在,呵呵,有些东西都忘记了,所以又花费了两天时间熟悉了下,又发现了一
些包括软件和硬件上的小 Bug,总算今天让它新鲜出炉了,enjoy it... ...好了,说了这么多,下面进
入正题了:
FlexBus,以前有博友问过我是什么 bus,呵呵,其实就是飞思卡尔自己的一种外部总线接口,
可以用来扩展诸如外部 ROM、SRAM、可编程逻辑器件或者一些从设备之类的,很灵活方便。我个
人觉着感觉挺好用的,自己也实际应用了,扩展了一片 ISSI 的 SRAM,用起来还是比较爽的,不过
最开始我的硬件设计上有点问题(建议看本篇的时候结合我写的关于 FlexBus 的硬件篇《说说 K60
的 FlexBus 外扩 SRAM 接口》,有些东西上篇提了我这里就不重点说了),现在给出改进后的硬件反
相电路,以前的 FB_AD0的频率达到500k bps 以上的时候,FB_AD0_B 就会跟不上,波形严重失真,
严重的时候三极管不能关断,结果造成反相失败,经过如下改进之后加了一个加速电容,减小集电极
电阻,又在基极加了泄流电阻,提高了三极管开关导通速率(这些是硬件设计的一些经验,这里需要
提一下,咱们这些搞嵌入式开发的,不能老是盯着单片机软件编程这一块,硬件设计很重要,有时候
硬件上的一点点改进有可能会提高你的工程质量一个档次),经过测试 FB_AD0达到1M 以上还是可
以正常工作的,不过如果条件允许的话还是建议用非门反相吧,我当初是为了节省板子面积才折衷了
三极管的方式,结果造成了很大的困扰,现在在 FlexBusClock 20M 以下还可以正常使用,再往上就
不敢保证了。
以上是对《说说 K60的 FlexBus 外扩 SRAM 接口》的那篇博客的补充和更正,呵呵,如果上篇已经
熟悉了,就直接跳到该段软件编程部分即可,软件编程部分,感觉还是比较简单的,思路较清晰,需
要操作的寄存器较少,只要在初始化阶段设置好几个寄存器就可以任意操作 FlexBus 总线了,呵呵,
下面就着重说说软件编程需要的几个寄存器了:
(1)FB_CSARn,即片选地址寄存器:
该寄存器即配置相应的外部片选信号 FB_CSn 的地址范围的(即基地址),即设定 BA 段为某个基地
址,当 MCU 寻址范围处在该基地址范围的时候,相应的 FB_CSn 为低电平,选中相应的外设,从而
进行进一步的读写操作。当然这里需要着重强调一下,这个基地址范围不是我们随意设置的,由
Kinetis 的内存映射可以看出来,该基地址只在该范围下有效(以前有过博友问过我这个问题,这个
地址不能随便设置的),如下:
(2)FB_CSMRn,我姑且叫它片选基地址屏蔽寄存器:
之所以叫它基地址屏蔽寄存器主要是 BAM 字段的作用了,由 FB_CSAR 寄存器可知,它只受32位总
线地址的高16位影响,如果设置 FB_CSARn=0x6000_0000,那么在寻址范围在
0x6000_0000~0x6000_FFFF 的范围内都是有效的(即 FB_CSn 有效),即 FlexBus 的最小寻址地址
块为2^16=64KB 大小,而如果你想要在该基地址范围下寻址更大的范围,嘿嘿,那就要用到 BAM
字段了,其作用我觉着用英语表达更容易理解,即 Setting a BAM bit causes the corresponding
CSAR bit to be a don’t care in the decode,直接这么说估计好些人不明白,那我就用例子说明一
下,设置 FB_CSAR[BA]=0x6000,FB_CSMR[BAM]=0x0001,则相应的 FB_CS 的片选范围为
0x6000_0000~0x6000_FFFF 和0x6001_0000~0x6001_FFFF 连续的128KB 的空间,即 BAM 相应
位的作用就是屏蔽了 BA 相应位在寻址译码上的作用。说完这个再说下地址连续性的概念,同样设置
FB_CSAR[BA]=0x6000,而 FB_CSMR[BAM]=0x0004的话,则相应的 FB_CS 的片选范围则是
0x6000_0000~0x6000_FFFF 和0x6004_0000~0x6004_FFFF 这两个不连续的128KB 的空间,而如
果设置 FB_CSMR[BAM]=0x0007的话,则寻址范围则为0x6000_0000~0x6007_FFFF 这连续512KB
的空间,呵呵,这个寄存器作用理解起来有点难,所以说了这么多,还没明白的还是继续啃英文
datasheet 吧。
最后要说说 FB_CSMR[V]这个位段,即片选有效信号,这里值得一提的是,MCU 复位之后只有 FB_CS0
有效,如果需要用到其他的片选信号,则必须先置位 FB_CSMR0[V](注意是 CSMR0),然后才能使
用其他片选信号。
(3)FB_CSCRn,即片选控制寄存器:
该寄存器也很重要,涉及到数据端口位数,对齐方式等等,这里就挑我们接下来的软件编程需要的说
说。FB_CSCR[PS],即数据端口大小,跟 FB_CSCR[BLS](对齐方式)配合,决定 FlexBus 数据总线
的端口的分配和大小,我由于采用了8位端口(见我的 FlexBus 的硬件电路设计篇)所以进行了相应
的设计。
(4)FB_CSPMCR,即 FlexBus 的引脚复用功能控制寄存器
这个寄存器涉及到一些复用的选择,根据个人实际应用来配置,所以具体内容还是根据 datasheet
来设置吧,这里就这么一提,琢磨深入的话还是钻进 E 文研究一番吧,哈哈~
主要的寄存器都介绍完了,其实还有 IO 管脚的复用寄存器,不过独属于 FlexBus 模块,而且在
以前的应用中也都用过,这里就不提了,下面废话不多说了,呵呵,直接上代码了,主要是两个函数
接口——FlexBus 的初始化函数和管脚复用选择函数(具体操作我都已经注释了,有中文有 E 文的,
至于为什么老用 E 文注释,是因为觉着有的时候用 E 文注释看起来更明白些,不知道有同感没,嘿嘿):
/*****************************************************************************************
** Routine: FlexBus_Init(to understand the workfolw, refer to datasheet page714)
** Description: initialize the FlexBus for extern SRAM
FB_CS
--- chip select(Chip_S0, Chip_S1, Chip_S2, Chip_S3, Chip_S4,
Chip_S5)
Block_1MB
BASE_ADDRESS--- the base address for the corresponding chip select
Port_Size
--- data port size(BIT_8, BIT_16, BIT_32)
Block_Size --- Block_64KB, Block_128KB, Block_256KB, Block_512KB,
*****************************************************************************************/
void FlexBus_Init(uint8 FB_CS, vuint16* BASE_ADDRESS, uint8 Port_Size, uint8 Block_Size)
{
// Chip select address resgister
FB_CSAR_REG(FB_BASE_PTR,FB_CS) = (uint32) BASE_ADDRESS;
/* Set base address. */
// Chip select control register
FB_CSCR_REG(FB_BASE_PTR,FB_CS) =
FB_CSCR_PS(Port_Size)
/* Set port size */
| FB_CSCR_AA_MASK
| FB_CSCR_ASET(0x1)
//
| FB_CSCR_BLS_MASK
/* Data is right justified on FB_AD,
FB_AD[15:0] */
| FB_CSCR_WS(0x1) ;
// Chip select mask register
/*
*/
* Note: At reset, no chip-select other than FB_CS0 can be used until
* the CSMR0[V] is set. Afterward, FB_CS[5:0] functions as programmed.
/* Set base address mask for corresponding address space */
FB_CSMR_REG(FB_BASE_PTR,FB_CS) =
FB_CSMR_BAM(Block_Size)
| FB_CSMR_V_MASK
;
/* Enable cs signal */
}
下面的函数我根据我的实际板子设计做了些更改,跟我当初上传的不太一样,注意下......
/*****************************************************************************************
** Routine: FlexBus_Pins_Multiplex
** Description: configure the pin muliplexing function according to the above seting
(FlexBus_Init).
Default setting: 20MHz FlexBus clock(Be setted in mcg);
2M*8bits space address
4 chip select signals(cs0, cs1, cs2, cs3)
*****************************************************************************************/
void FlexBus_Pins_Multiplex(void)
{
// Chip select port multiplexing control register
FB_CSPMCR = FB_CSPMCR_GROUP1(1)
/* FB_CS1 */
| FB_CSPMCR_GROUP2(0)
/* FB_CS4 */
| FB_CSPMCR_GROUP3(0)
/* FB_CS5 */
| FB_CSPMCR_GROUP4(1)
/* FB_CS2 */
| FB_CSPMCR_GROUP5(1)
/* FB_CS3 */
;
//SIM_CLKDIV1 |= SIM_CLKDIV1_OUTDIV3(0x3);
/* Has been setted in mcg.c file */
/*
* Configure the pins needed to FlexBus Function (Alt 5)
* this example uses low drive strength settings
*/
//address
PORTB_PCR9 = PORT_PCR_MUX(5);
//
fb_ad[20]
PORTB_PCR10 = PORT_PCR_MUX(5);
//
fb_ad[19]
PORTB_PCR11 = PORT_PCR_MUX(5);
//
fb_ad[18]
PORTB_PCR16 = PORT_PCR_MUX(5);
//
fb_ad[17]
PORTB_PCR17 = PORT_PCR_MUX(5);
//
fb_ad[16]
PORTB_PCR18 = PORT_PCR_MUX(5);
//
fb_ad[15]
PORTC_PCR0 = PORT_PCR_MUX(5);
//
fb_ad[14]
PORTC_PCR1 = PORT_PCR_MUX(5);
//
fb_ad[13]
PORTC_PCR2 = PORT_PCR_MUX(5);
//
fb_ad[12]
PORTC_PCR4 = PORT_PCR_MUX(5);
//
fb_ad[11]
PORTC_PCR5 = PORT_PCR_MUX(5);
//
fb_ad[10]
PORTC_PCR6 = PORT_PCR_MUX(5);
//
fb_ad[9]
PORTC_PCR7 = PORT_PCR_MUX(5);
//
fb_ad[8]
PORTC_PCR8 = PORT_PCR_MUX(5);
//
fb_ad[7]
PORTC_PCR9 = PORT_PCR_MUX(5);
//
fb_ad[6]
PORTC_PCR10 = PORT_PCR_MUX(5);
//
fb_ad[5]
PORTD_PCR2 = PORT_PCR_MUX(5);
//
fb_ad[4]
PORTD_PCR3 = PORT_PCR_MUX(5);
//
fb_ad[3]
PORTD_PCR4 = PORT_PCR_MUX(5);
//
fb_ad[2]
PORTD_PCR5 = PORT_PCR_MUX(5);
//
fb_ad[1]
PORTD_PCR6 = PORT_PCR_MUX(5);
//
fb_ad[0]
//data
PORTB_PCR20 = PORT_PCR_MUX(5);
//
fb_ad[31] used as d[7]
PORTB_PCR21 = PORT_PCR_MUX(5);
//
fb_ad[30] used as d[6]
PORTB_PCR22 = PORT_PCR_MUX(5);
//
fb_ad[29] used as d[5]
PORTB_PCR23 = PORT_PCR_MUX(5);
//
fb_ad[28] used as d[4]
PORTC_PCR12 = PORT_PCR_MUX(5);
//
fb_ad[27] used as d[3]