我是靠谱客的博主 纯情外套,最近开发中收集的这篇文章主要介绍Zynq-Linux移植学习笔记之17-Zynq下linuxPL部分Flash,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述


 

1、  背景介绍

在板上,ZYNQ PL部分通过EMC连接一片NOR FLASH,地址空间如下:


可以看到NOR FLASH的起始地址为0x80000000,这是物理地址,可以把数据存放在以该地址起始的一段区域。

需要注意的是,在对NOR FLASH进行读写数据时,需要参考对应的datasheet,例如这里选用的NOR FLASH读、写、擦除步骤如下:





通过上面的表格就知道进行相应操作每一步该做什么,可以转换为SDK中裸奔程序的C代码。

 

2、  Linux下flash操作

之前提到过zynq中Linux用户应用程序可以通过/dev/mem访问到物理地址,xil_in32和xil_out32等裸奔程序中常见的函数可以通过这一机制移植到linux下。于是,对flash的操作其实就是基于xil_in和xil_out对物理地址进行读写。

这里只需要实现三个函数,erase,write_sector以及read_sector.代码如下:

 


  1. //xil_io.h
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdint.h>
  5. #include <string.h>
  6. #include <sys/types.h>
  7. #include <sys/stat.h>
  8. #include <sys/mman.h>
  9. #include <unistd.h>
  10. #include <fcntl.h>
  11. #define PAGE_SIZE ((size_t)getpagesize())
  12. #define PAGE_MASK ((uint64_t) (long)~(PAGE_SIZE - 1))
  13. void Xil_Out32(uint64_t phyaddr, uint32_t val)
  14. {
  15. int fd;
  16. volatile uint8_t *map_base;
  17. uint64_t base = phyaddr & PAGE_MASK;
  18. uint64_t pgoffset = phyaddr & (~PAGE_MASK);
  19. if((fd = open( "/dev/mem", O_RDWR | O_SYNC)) == -1)
  20. {
  21. perror( "open /dev/mem:");
  22. }
  23. map_base = mmap( NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
  24. fd, base);
  25. if(map_base == MAP_FAILED)
  26. {
  27. perror( "mmap:");
  28. }
  29. *( volatile uint32_t *)(map_base + pgoffset) = val;
  30. close(fd);
  31. munmap(( void *)map_base, PAGE_SIZE);
  32. }
  33. int Xil_In32(uint64_t phyaddr)
  34. {
  35. int fd;
  36. uint32_t val;
  37. volatile uint8_t *map_base;
  38. uint64_t base = phyaddr & PAGE_MASK;
  39. uint64_t pgoffset = phyaddr & (~PAGE_MASK);
  40. //open /dev/mem
  41. if((fd = open( "/dev/mem", O_RDWR | O_SYNC)) == -1)
  42. {
  43. perror( "open /dev/mem:");
  44. }
  45. //mmap
  46. map_base = mmap( NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
  47. fd, base);
  48. if(map_base == MAP_FAILED)
  49. {
  50. perror( "mmap:");
  51. }
  52. val = *( volatile uint32_t *)(map_base + pgoffset);
  53. close(fd);
  54. munmap(( void *)map_base, PAGE_SIZE);
  55. return val;
  56. }
  57. void Xil_Out16(uint64_t phyaddr, uint16_t val)
  58. {
  59. int fd;
  60. volatile uint8_t *map_base;
  61. uint64_t base = phyaddr & PAGE_MASK;
  62. uint64_t pgoffset = phyaddr & (~PAGE_MASK);
  63. if((fd = open( "/dev/mem", O_RDWR | O_SYNC)) == -1)
  64. {
  65. perror( "open /dev/mem:");
  66. }
  67. map_base = mmap( NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
  68. fd, base);
  69. if(map_base == MAP_FAILED)
  70. {
  71. perror( "mmap:");
  72. }
  73. *( volatile uint16_t *)(map_base + pgoffset) = val;
  74. close(fd);
  75. munmap(( void *)map_base, PAGE_SIZE);
  76. }
  77. int Xil_In16(uint64_t phyaddr)
  78. {
  79. int fd;
  80. uint16_t val;
  81. volatile uint8_t *map_base;
  82. uint64_t base = phyaddr & PAGE_MASK;
  83. uint64_t pgoffset = phyaddr & (~PAGE_MASK);
  84. //open /dev/mem
  85. if((fd = open( "/dev/mem", O_RDWR | O_SYNC)) == -1)
  86. {
  87. perror( "open /dev/mem:");
  88. }
  89. //mmap
  90. map_base = mmap( NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
  91. fd, base);
  92. if(map_base == MAP_FAILED)
  93. {
  94. perror( "mmap:");
  95. }
  96. val = *( volatile uint16_t *)(map_base + pgoffset);
  97. close(fd);
  98. munmap(( void *)map_base, PAGE_SIZE);
  99. return val;
  100. }
  101. void Xil_Out8(uint64_t phyaddr, uint16_t val)
  102. {
  103. int fd;
  104. volatile uint8_t *map_base;
  105. uint64_t base = phyaddr & PAGE_MASK;
  106. uint64_t pgoffset = phyaddr & (~PAGE_MASK);
  107. if((fd = open( "/dev/mem", O_RDWR | O_SYNC)) == -1)
  108. {
  109. perror( "open /dev/mem:");
  110. }
  111. map_base = mmap( NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
  112. fd, base);
  113. if(map_base == MAP_FAILED)
  114. {
  115. perror( "mmap:");
  116. }
  117. *( volatile uint8_t *)(map_base + pgoffset) = val;
  118. close(fd);
  119. munmap(( void *)map_base, PAGE_SIZE);
  120. }
  121. int Xil_In8(uint64_t phyaddr)
  122. {
  123. int fd;
  124. uint8_t val;
  125. volatile uint8_t *map_base;
  126. uint64_t base = phyaddr & PAGE_MASK;
  127. uint64_t pgoffset = phyaddr & (~PAGE_MASK);
  128. //open /dev/mem
  129. if((fd = open( "/dev/mem", O_RDWR | O_SYNC)) == -1)
  130. {
  131. perror( "open /dev/mem:");
  132. }
  133. //mmap
  134. map_base = mmap( NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
  135. fd, base);
  136. if(map_base == MAP_FAILED)
  137. {
  138. perror( "mmap:");
  139. }
  140. val = *( volatile uint8_t *)(map_base + pgoffset);
  141. close(fd);
  142. munmap(( void *)map_base, PAGE_SIZE);
  143. return val;
  144. }

 


  1. //move.h
  2. #ifndef SMARTCARMOVE_H
  3. #define SMARTCARMOVE_H
  4. #include <stdio.h>
  5. #include <fcntl.h>
  6. #include <unistd.h>
  7. #include <string.h>
  8. #include <sys/time.h>
  9. #include <sys/stat.h>
  10. #include <sys/types.h>
  11. #include <syslog.h>
  12. #include <memory.h>
  13. static int fd;
  14. #define MODE (O_WRONLY | O_TRUNC)
  15. #define SECSIZE 65536
  16. #define XPAR_AXI_EMC_0_S_AXI_MEM0_BASEADDR 0x80000000
  17. #define WAIT_TICKS 0xffffffff
  18. typedef unsigned short u16;
  19. extern void flash_set16(unsigned int addrBase,unsigned int addrOffset,unsigned int value);
  20. extern int flash_get16(unsigned int addrBase,unsigned int addrOffset);
  21. extern int Erase_Flash(int sectorNum);
  22. extern int Write_Sector(int sectorNum,int offset,u16 *src_addr,int wr_num);
  23. extern int Read_Sector(int sectorNum,int rd_num,unsigned short *buf);
  24. #endif

 


  1. #include "xil_io.h"
  2. #include "move.h"
  3. /**
  4. read and write phy mem
  5. * */
  6. void flash_set16(unsigned int addrBase,unsigned int addrOffset,unsigned int value)
  7. {
  8. Xil_Out16(addrBase+ 2*addrOffset, value);
  9. //printf("flash set reg 0x%x value is 0x%xn",addrBase+2*addrOffset,value);
  10. }
  11. int flash_get16(unsigned int addrBase,unsigned int addrOffset)
  12. {
  13. int ans= 0;
  14. ans=Xil_In16(addrBase+ 2*addrOffset);
  15. return ans;
  16. }
  17. int Erase_Flash(int sectorNum)
  18. {
  19. unsigned short flag;
  20. int i= 0;
  21. int val= 0;
  22. unsigned short *base_addr;
  23. base_addr = ( unsigned short*)(XPAR_AXI_EMC_0_S_AXI_MEM0_BASEADDR+SECSIZE*sectorNum* 2);
  24. printf( "erase start addr 0x%xn",base_addr);
  25. flash_set16(base_addr, 0x555, 0x00AA);
  26. flash_set16(base_addr, 0x2AA, 0x0055);
  27. flash_set16(base_addr, 0x555, 0x0080);
  28. flash_set16(base_addr, 0x555, 0x00AA);
  29. flash_set16(base_addr, 0x2AA, 0x0055);
  30. flash_set16(base_addr, 0, 0x0030);
  31. val=flash_get16(base_addr, 0);
  32. printf( "base addr 0x%x val is 0x%xn",base_addr,val);
  33. while((val& 0x80)!= 0x80)
  34. {
  35. i++;
  36. if( i>=WAIT_TICKS)
  37. {
  38. printf( "addr %x Erase_Flash failed!n",base_addr);
  39. flash_set16(base_addr, 0x555, 0x0090);
  40. flash_set16(base_addr, 0x000, 0x0000);
  41. return -1;
  42. }
  43. //flag = base_addr;
  44. val=flash_get16(base_addr, 0);
  45. }
  46. flash_set16(base_addr, 0x555, 0x0090);
  47. flash_set16(base_addr, 0x000, 0x0000);
  48. printf( "erase end addr %xn",base_addr+SECSIZE);
  49. return 0;
  50. }
  51. int Write_Sector(int sectorNum,int offset,u16 *src_addr,int wr_num)
  52. {
  53. int i,j;
  54. u16 *dst_addr;
  55. int val= 0;
  56. int ans= 0;
  57. dst_addr = (u16*)(XPAR_AXI_EMC_0_S_AXI_MEM0_BASEADDR+SECSIZE*sectorNum* 2+offset);
  58. /* Unlock Bypass program */
  59. flash_set16(dst_addr, 0x555, 0x00AA);
  60. flash_set16(dst_addr, 0x2AA, 0x0055);
  61. printf( "dst addr is 0x%xn",dst_addr);
  62. for(i= 0;i<wr_num;i++)
  63. {
  64. flash_set16(dst_addr, 0x555, 0x0020);
  65. flash_set16(dst_addr, 0x000, 0x00A0);
  66. // printf("i is %dn",i);
  67. val=src_addr[i];
  68. printf( "val is 0x%xn",val);
  69. flash_set16(dst_addr,i,val);
  70. ans=flash_get16(dst_addr,i);
  71. //printf("ans is 0x%xn",ans);
  72. j= 0;
  73. while( ans!= val)
  74. {
  75. j++;
  76. if(j>=WAIT_TICKS)
  77. {
  78. flash_set16(dst_addr, 0x555, 0x0090);
  79. flash_set16(dst_addr, 0x000, 0x0000);
  80. return -1;
  81. }
  82. ans=flash_get16(dst_addr,i);
  83. }
  84. }
  85. flash_set16(dst_addr, 0x555, 0x0090);
  86. flash_set16(dst_addr, 0x000, 0x0000);
  87. return 0;
  88. }
  89. int Read_Sector(int sectorNum,int rd_num,unsigned short *buf)
  90. {
  91. unsigned short *sector_addr;
  92. int i;
  93. int val= 0;
  94. if( rd_num <= 0)
  95. {
  96. return -1;
  97. }
  98. printf( "flash read start--sectorNum= %d rd_num= %dn",sectorNum,rd_num);
  99. sector_addr = (u16*)(XPAR_AXI_EMC_0_S_AXI_MEM0_BASEADDR+SECSIZE*sectorNum* 2);
  100. printf( "sector addr is 0x%xn",sector_addr);
  101. if( rd_num <= SECSIZE )
  102. {
  103. for(i= 0;i<rd_num;i++)
  104. {
  105. printf( "val is 0x%xn",flash_get16(sector_addr, 0));
  106. val = flash_get16(sector_addr, 0);
  107. *buf=val;
  108. buf++;
  109. sector_addr++;
  110. }
  111. }
  112. else
  113. {
  114. printf( "errorn");
  115. }
  116. return 0;
  117. }
  118. int main(int argc, char *argv[])
  119. {
  120. //Erase_Flash(1);
  121. u16 dat[ 100];
  122. int i;
  123. Read_Sector( 0, 10,dat);
  124. for(i= 0;i< 10;i++)
  125. {
  126. printf( "0x%xn",dat[i]);
  127. }
  128. /*
  129. for(i=0;i<100;i++)
  130. {
  131. dat[i]=10+i;
  132. }
  133. Erase_Flash(0);
  134. Write_Sector(0,0,dat,10);
  135. */
  136. return 0;
  137. }

3、  测试

这里没有驱动的概念,一切都放在用户态执行,编译产生flash应用程序,放到板子上执行程序进行测试即可。注意,写之前要擦除。

下图为写文件的测试,这里写了10个数:


写完以后再读


可以看到,读出来的和写入的值一样,测试通过。

 

4、  补充

关于/dev/mem可以看看下面这段代码,写的很详细,用户态直接访问物理地址,对于ZYNQ中PL部分的操作确实帮助极大。

 


  1. /*
  2. * devmem2.c: Simple program to read/write from/to any location in memory.
  3. *
  4. * Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
  5. *
  6. *
  7. * This software has been developed for the LART computing board
  8. * (http://www.lart.tudelft.nl/). The development has been sponsored by
  9. * the Mobile MultiMedia Communications (http://www.mmc.tudelft.nl/)
  10. * and Ubiquitous Communications (http://www.ubicom.tudelft.nl/)
  11. * projects.
  12. *
  13. * The author can be reached at:
  14. *
  15. * Jan-Derk Bakker
  16. * Information and Communication Theory Group
  17. * Faculty of Information Technology and Systems
  18. * Delft University of Technology
  19. * P.O. Box 5031
  20. * 2600 GA Delft
  21. * The Netherlands
  22. *
  23. *
  24. * This program is free software; you can redistribute it and/or modify
  25. * it under the terms of the GNU General Public License as published by
  26. * the Free Software Foundation; either version 2 of the License, or
  27. * (at your option) any later version.
  28. *
  29. * This program is distributed in the hope that it will be useful,
  30. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  31. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  32. * GNU General Public License for more details.
  33. *
  34. * You should have received a copy of the GNU General Public License
  35. * along with this program; if not, write to the Free Software
  36. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  37. *
  38. */
  39. #include <stdio.h>
  40. #include <stdlib.h>
  41. #include <unistd.h>
  42. #include <string.h>
  43. #include <errno.h>
  44. #include <signal.h>
  45. #include <fcntl.h>
  46. #include <ctype.h>
  47. #include <termios.h>
  48. #include <sys/types.h>
  49. #include <sys/mman.h>
  50. #define FATAL do { fprintf(stderr, "Error at line %d, file %s (%d) [%s]n",
  51. __LINE__, __FILE__, errno, strerror(errno)); exit(1); } while(0)
  52. #define MAP_SIZE 4096UL
  53. #define MAP_MASK (MAP_SIZE - 1)
  54. int main(int argc, char **argv) {
  55. int fd;
  56. void *map_base, *virt_addr;
  57. unsigned long read_result, writeval;
  58. off_t target;
  59. int access_type = 'w';
  60. if(argc < 2) {
  61. fprintf( stderr, "nUsage:t%s { address } [ type [ data ] ]n"
  62. "taddress : memory address to act uponn"
  63. "ttype : access operation type : [b]yte, [h]alfword, [w]ordn"
  64. "tdata : data to be writtennn",
  65. argv[ 0]);
  66. exit( 1);
  67. }
  68. target = strtoul(argv[ 1], 0, 0);
  69. if(argc > 2)
  70. access_type = tolower(argv[ 2][ 0]);
  71. if((fd = open( "/dev/mem", O_RDWR | O_SYNC)) == -1) FATAL;
  72. printf( "/dev/mem opened.n");
  73. fflush( stdout);
  74. /* Map one page */
  75. map_base = mmap( 0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
  76. if(map_base == ( void *) -1) FATAL;
  77. printf( "Memory mapped at address %p.n", map_base);
  78. fflush( stdout);
  79. virt_addr = map_base + (target & MAP_MASK);
  80. switch(access_type) {
  81. case 'b':
  82. read_result = *(( unsigned char *) virt_addr);
  83. break;
  84. case 'h':
  85. read_result = *(( unsigned short *) virt_addr);
  86. break;
  87. case 'w':
  88. read_result = *(( unsigned long *) virt_addr);
  89. break;
  90. default:
  91. fprintf( stderr, "Illegal data type '%c'.n", access_type);
  92. exit( 2);
  93. }
  94. printf( "Value at address 0x%X (%p): 0x%Xn", target, virt_addr, read_result);
  95. fflush( stdout);
  96. if(argc > 3) {
  97. writeval = strtoul(argv[ 3], 0, 0);
  98. switch(access_type) {
  99. case 'b':
  100. *(( unsigned char *) virt_addr) = writeval;
  101. read_result = *(( unsigned char *) virt_addr);
  102. break;
  103. case 'h':
  104. *(( unsigned short *) virt_addr) = writeval;
  105. read_result = *(( unsigned short *) virt_addr);
  106. break;
  107. case 'w':
  108. *(( unsigned long *) virt_addr) = writeval;
  109. read_result = *(( unsigned long *) virt_addr);
  110. break;
  111. }
  112. printf( "Written 0x%X; readback 0x%Xn", writeval, read_result);
  113. fflush( stdout);
  114. }
  115. if(munmap(map_base, MAP_SIZE) == -1) FATAL;
  116. close(fd);
  117. return 0;
  118. }


 

运行截图如下:



最后

以上就是纯情外套为你收集整理的Zynq-Linux移植学习笔记之17-Zynq下linuxPL部分Flash的全部内容,希望文章能够帮你解决Zynq-Linux移植学习笔记之17-Zynq下linuxPL部分Flash所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部