当前位置: 首页 > news >正文

html网站建设流程图/厦门seo顾问屈兴东

html网站建设流程图,厦门seo顾问屈兴东,网站框架有哪些,房地产开发公司排名概述: Cortex-m0的integration_kit提供三个GPIO接口,其中GPIO0传输到外部供用户使用,为EXTGPIO;GPIO1是内核自己的信号,不能乱改,会崩掉;GPIO2是一些中断,这里没开中断,可…

概述:

    Cortex-m0的integration_kit提供三个GPIO接口,其中GPIO0传输到外部供用户使用,为EXTGPIO;GPIO1是内核自己的信号,不能乱改,会崩掉;GPIO2是一些中断,这里没开中断,可以读写相应的寄存器。

1. 寄存器寻址,先看手册:

 

这里倒没什么特别,第10位为1正好对应地址0x400,为DIR寄存器,同理0x410对应中断寄存器。

对应硬件描述语言:

 // 本GPIO设备被选通、总线写、总线传输类型为连续或不连续时有效wire        write_trans  = HSEL & HWRITE & HTRANS[1];// 写信号有效时根据地址选择要写入的寄存器 wire nxt_gpiodata_o_wren = write_trans & (HADDR[10 ] == 1'b0); wire nxt_gpiodir_wren = write_trans & (HADDR[10: 4] == 7'b1000000); wire nxt_gpiointmask_wren = write_trans & (HADDR[10: 4] == 7'b1000001);
//-----------------------------------------------------------------------------
// AHB register read mux
//----------------------------------------------------------------------------- // Drive read mux next state from word address when selected wire [10:4] nxt_read_mux = HSEL ? HADDR[10:4] : read_mux; always @(posedge HCLK or negedge HRESETn) if(~HRESETn) read_mux <= 7'b0; // Set select to input on reset else if(HREADY) // When bus is ready read_mux <= nxt_read_mux; // assign mux select next value wire [31:0] rdata = (read_mux[10: 4] == 7'b1000000)? gpiodir : ( //Offset 0x400 returns Direction Register (read_mux[10: 4] == 7'b1000001)? gpiointmask : ( //Offset 0x410 returns Interrupt Mask Register (read_mux[10 ] == 1'b0)? gpiodata_i : 32'b0)); //Offset 0x0 to 0x3ff returns Data Register

 2. GPIODATA读写

这个特别麻烦,手册里说的特别简洁,对应verilog一大堆。

 

首先是这个Note当初没有仔细看,后来做实验出问题也没想到,直到写这篇总结才发现,人家还给配了图,特意用来表明:gpio模块用了两个寄存器,两个寄存器是独立的。

看图说话:

 

然后总线的读数据HRDATA永远只读取mask过以后的gpio_in寄存器,总线的HWDATA永远能向gpio_out寄存器写入数据,自画丑图如下:

 

verilog:

//-----------------------------------------------------------------------------
// IO Pad registers
//-----------------------------------------------------------------------------assign      GPIOEN         = gpiodir;assign      GPIOOUT        = gpiodata_o;wire [31:0] nxt_gpiodata_i = GPIOIN;
// Combine bus and register values using mask for next state of Data Out Registerwire [31:0] nxt_gpiodata_o = gpiodata_o_wren ?((HWDATA & type_mask2) | (gpiodata_o & ~type_mask2)): gpiodata_o;always @(posedge HCLK or negedge HRESETn)if(~HRESETn)begingpiodir     <= {32{1'b0}};      // Disable all buffers on resetgpiointmask <= {32{1'b0}};gpiodata_o  <= {32{1'b0}};endelse if (HREADY)                    // When bus is ready:begingpiodir     <= nxt_gpiodir;     // update direction registergpiointmask <= nxt_gpiointmask; // update interrupt mask registergpiodata_o  <= nxt_gpiodata_o;  // updata data out registerendalways @ (posedge FCLK or negedge HRESETn)if(~HRESETn)gpiodata_i   <= {32{1'b0}};      // Reset all outputs to zeroelsegpiodata_i   <= nxt_gpiodata_i;  // Sample GPIOIN continuously
assign HRDATA = rdata & type_mask2;

并且gpiodata_i这个寄存器的赋值是在FCLK时钟域(HCLK是FCLK的门控时钟,二者同频同相),这么设计为什么暂时不太懂,是害怕漏掉信号的变化?

可以看到,这里对总线读数据HRDATA和gpiodata_o寄存器的写入用的是同一组mask信号:type_mask2,这个mask信号得来不易,先看代码:

//-----------------------------------------------------------------------------
// AHB register read/write mask for byte accesses on Data register
//----------------------------------------------------------------------------- wire nxt_hsize_zero = (HSIZE[1:0] == 2'b0) & HSEL; always @ (hsize_zero or haddr_r or mask8 or type_mask) case({hsize_zero,haddr_r}) 3'b100 : type_mask2 = {8'h00, 8'h00, 8'h00, mask8}; 3'b101 : type_mask2 = {8'h00, 8'h00, mask8, 8'h00}; 3'b110 : type_mask2 = {8'h00, mask8, 8'h00, 8'h00}; 3'b111 : type_mask2 = {mask8, 8'h00, 8'h00, 8'h00}; 3'b000,3'b001,3'b010,3'b011: type_mask2 = type_mask; default : type_mask2 = {32{1'bx}}; endcase

type_mask2的真身,可以看到,当hsize_zero为0时type_mask2直接等于type_mask,hsize_zero顾名思义,就是HSIZE为0时有效,这里有点绕,总的来说就是,当HSIZE[1:0]不为0时(字或半字访问),type_mask2=type_mask,再看type_mask

//-----------------------------------------------------------------------------
// AHB write byte address control
//-----------------------------------------------------------------------------// Decode term for access to least significant bytewire        nxt_byte0 = ( HSIZE[1] ) |( HSIZE[0] & ~HADDR[1] ) |( ~HSIZE[0] & ~HADDR[1] & ~HADDR[0] );// Decode term for access to byte 1wire        nxt_byte1 = ( HSIZE[1] ) |( HSIZE[0] & ~HADDR[1] ) |( ~HSIZE[0] & ~HADDR[1] &  HADDR[0] );// Decode term for access to byte 2wire        nxt_byte2 = ( HSIZE[1] ) |( HSIZE[0] &  HADDR[1] ) |( ~HSIZE[0] &  HADDR[1] & ~HADDR[0] );// Decode term for access to most significant bytewire        nxt_byte3 = ( HSIZE[1] ) |               //整个字-32bit访问( HSIZE[0] &  HADDR[1] ) |        //半字访问--16bit访问的情况( ~HSIZE[0] &  HADDR[1] &  HADDR[0] ); //字节访问--8bitalways @(posedge HCLK or negedge HRESETn)// when bus is ready,byte[3:0] <= nxt_byte[3:0];(这里删去了,为了方便看)wire [31:0] type_mask = { {8{byte3}}, {8{byte2}}, {8{byte1}}, {8{byte0}} };

就是字节使能,HSIZE是总线传输规模,根据AMBA3 AHB Lite手册:

 

    HSIZE[1]=1时是32bit传输,此时type_mask=32'hFFFF_FFFF

    HSIZE[1]=0时,看HSIZE[0]

             当HSIZE[0]=1时半字访问,再参考总线地址HADDR[1]的状态,看要访问上半字还是下半字,此时:

                        如果HADDR[1]=0,type_mask=32'h0000_FFFF

                        如果HADDR[1]=1,type_mask=32'hFFFF_0000

                        --而HADDR[0]的值是多少,是不care的。

            当HSIZE[0]=0时字节访问,type_mask根据HADDR[1:0]的值分别令对应的字节为1:

                        如果HADDR[1:0]=00,type_mask=32'h0000_00FF

                        如果HADDR[1:0]=01,type_mask=32'h0000_FF00

                        如果HADDR[1:0]=10,type_mask=32'h00FF_0000 

                        如果HADDR[1:0]=11,type_mask=32'hFF00_0000

以GPIO0的访问为例,如下:

  

 总的来说就是:总线字(32bit)或半字(16bit)访问GPIO时,不进行位mask,只有字节(8bit)访问时mask8才有用武之地,下面是mask8:

// For byte accesses, the mask is in HADDR[9:2]wire [7:0]  nxt_mask8 = (nxt_hsize_zero)? HADDR[9:2] : {8{1'b0}};always @(posedge HCLK or negedge HRESETn)if(~HRESETn)mask8 <= {8{1'b0}};      // Reset mask to FFelse if(HREADY)mask8 <= nxt_mask8;      // Update AHB mask with next

其实非常简单粗暴,直接等于HADDR[9:0],并且手册里也给出了说明:

 

 

但是好死不死,给的例子也太不恰当了,写0x40000009访问第9bit,那是不是写0x40000008访问第8bit,那不是一直访问到0x40000020就行了,GPIODATA范围可是0x00~0x3ff,留这么多空间是要做啥?

并且,提供的软件程序(cm0pikmcu.h)都是这样的定义:

 1 /*--------------------- General Purpose Input and Ouptut ---------------------*/
 2 typedef union  3 {  4  __IO uint32_t WORD;  5 __IO uint16_t HALFWORD[2];  6 __IO uint8_t BYTE[4];  7 } GPIO_Data_TypeDef;  8  9 typedef struct 10 { 11 GPIO_Data_TypeDef DATA [256]; 12  GPIO_Data_TypeDef DIR; 13 uint32_t RESERVED[3]; 14  GPIO_Data_TypeDef IE; 15 } GPIO_TypeDef;

访问方式:

GPIO0->DATA[0].WORD = 0x55;

没看verilog之前怎么也理解不上去这个定义,想着GPIO,不就一个寄存器吗,自己写呗,于是有了下面的代码:

*(u32 *)(0x40000400) = 0xffffffff;    //配置GPIO0->DIR寄存器为输出
*(u8 *)(0x40000000) = 0x55;           //-现象:写不进去
*(u32 *)(0x40000000) = 0x12345678;    //-现象:可以写,但总有几位写不进去。

事实上,GPIODATA的正确写入方式是:

 

不进行位屏蔽,按字节访问GPIO寄存器的正确方式:

C代码示例:

unsigned char c0, c1, c2, c3;*(unsigned int *)(0x40001400) = 0xffffffff;         //GPIO2设为输出*(unsigned int *)(0x40001000) = 0xa5a5a5a5;         //32bit写时无mask*(unsigned short *)(0x40001000) = 0xff3c;           //16bit写时无mask*(unsigned short *)(0x40001002) = 0xc300;           //16bit写时无mask         *(unsigned int *)(0x40001000) = 0x12345678;*(unsigned char *)(0x400013FC) = 0x55;              //字节写,令mask=8,8bit全部写入*(unsigned char *)(0x400013FD) = 0x55;*(unsigned char *)(0x400013FE) = 0x55;*(unsigned char *)(0x400013FF) = 0x55;c0 = *(unsigned char *)(0x400013FC);c1 = *(unsigned char *)(0x400013FD);c2 = *(unsigned char *)(0x400013FE);c3 = *(unsigned char *)(0x400013FF);*(unsigned char *)(0x400013FD)     = 0xaa;c0 = *(unsigned char *)(0x400013FC);c1 = *(unsigned char *)(0x400013FD);c2 = *(unsigned char *)(0x400013FE);c3 = *(unsigned char *)(0x400013FF);

无论是memory查看还是读取到变量都没问题。

 

并且,由于GPIO模块内部的输入、输出寄存器没有互联,如果硬件上不在GPIO模块外把输出给到输入,你是永远也无法在KEIL里看到刚刚写进去的数据的。integration_kit里对例化的三个GPIO配置如下:

 

通过COMPIKMCU.v里32个buffer实现的:

  bufif1 (EXTGPIO[31], mcu_extgpioout[31], mcu_extgpioen[31]);assign mcu_extgpioin = EXTGPIO;

 

GPIO1和GPIO2没有引到外部,在MCU.v的上一层,cm0p_ik_sys.v里一个赋值语句实现:

  assign sys_gpio2in           = sys_gpio2out;

 其实GPIO1还比较复杂,并不全是输出给输入,反正是core的信号,没事先别乱动,比如像这样:

  assign sys_gpio1in[23:22]    = sys_gpio1out[23:22];assign sys_gpio1in[21]       = sys_halted;assign sys_gpio1in[20]       = sys_lockup;assign sys_gpio1in[19]       = SLEEPDEEP;

 3. GPIO模块对总线的响应:

//-----------------------------------------------------------------------------
// AHB tie offs
//-----------------------------------------------------------------------------assign      HREADYOUT = 1'b1;        // All accesses to GPIO are zero-waitassign      HRESP     = 1'b0;        // Generate OK responses only

 也就是说GPIO模块永远响应OK,且完全按AHB-Lite定义的读写时序,第一个HCLK写地址,第二个HCLK读或写数据

 

 

转载于:https://www.cnblogs.com/zhengmeisong/p/7665832.html

http://www.jmfq.cn/news/5293657.html

相关文章:

  • github主页做网站/seo课程培训要多少钱
  • 做网站邢台/广州软文推广公司
  • 如何做网站推广赚钱/重庆seo排名方法
  • 网站左侧 导航/浙江关键词优化
  • 规模以上工业企业分析/seo搜索如何优化
  • av插插网站正在建设中/2024新闻热点摘抄
  • 泉州厦门网站建设公司/搜索引擎优化的报告
  • 北京网站设计制作关键词优化/武汉网站营销seo方案
  • 家乡网站建设策划书/济南seo快速霸屏
  • 日本网站代理/友情链接名词解释
  • 辽宁网站建设论坛/网络竞价
  • 网站线框/新手怎么入行sem
  • wordpress bootstrap 企业/seo刷排名公司
  • 网站设计制作花多少钱/软文广告
  • 西安网站建设huanxi/百度免费推广方法
  • 建设网站需要哪个语言编译器/四川全网推网络推广
  • 网站开发的名称叫什么/营销策略有哪些4种
  • 凡科网站免费版/百度页面
  • 织梦cms收费不交有事吗/岳阳seo公司
  • 小黄人大电影免费观看/seo排名大概多少钱
  • 网站用oracle做数据库/手游推广去哪里找客源
  • 北京网站开发怎么做/百度商城app
  • 自己做免费的网站/深圳排名seo公司
  • 嵊州做网站/今日特大新闻新事
  • 承包企业管理系统/企业网站seo排名
  • 住建城乡建设网站/互联网营销培训班
  • 网站远程数据库/如何做运营推广
  • wordpress入门建站/佛山外贸seo
  • 网站做区块链然后往里面投钱/百度地图在线查询
  • 永州做网站/广州网络营销选择