5508|0

74

帖子

2

TA的资源

一粒金砂(中级)

楼主
 

BB方案大结局之BB端软件实现篇——基于BB及FPGA的DAQ及DDS设计与实现 [复制链接]

本帖最后由 黑非拉 于 2014-6-22 19:01 编辑

BB方案大结局之BB端软件实现篇——基于BB及FPGA的高速数据采集及DDS信号发生器设计与实现1)开发平台及语言为:
Linux C
2)主要包括如下三个层次:
系统层:
BB管脚配置,对应板文件的修改。
驱动层:
DDS芯片AD9832驱动;
读写FPGA的GPMC驱动。
应用层:
TCPServer Socket通信;
DDS芯片控制;
GPMC读写FPGA:DDS波形数据及频率控制字设置(GPMC写),数据采集与传输(GPMC读);
CAN通信(本方案没有用到,实际项目中用过)。
3)系统层的BB管脚配置
需要修改板文件board-am335xevm.c的内容,该文件路径如下:
  1. root@gao:~# cd bone-linux/arch/arm/mach-omap2/
  2. root@gao:~/bone-linux/arch/arm/mach-omap2# ls board-am335xevm.c
  3. board-am335xevm.c
复制代码
关键部分代码:
  1. /* Beaglebone Rev A3 and after */
  2. static struct evm_dev_cfg beaglebone_dev_cfg[] = {
  3.         {tps65217_init,        DEV_ON_BASEBOARD, PROFILE_NONE},
  4.         {mii1_init,        DEV_ON_BASEBOARD, PROFILE_NONE},
  5.         {usb0_init,        DEV_ON_BASEBOARD, PROFILE_NONE},
  6.         {usb1_init,        DEV_ON_BASEBOARD, PROFILE_NONE},
  7.         {mmc0_init,        DEV_ON_BASEBOARD, PROFILE_NONE},
  8.         {dcan0_beaglebone_init, DEV_ON_BASEBOARD, PROFILE_NONE},
  9.         {dcan1_beaglebone_init, DEV_ON_BASEBOARD, PROFILE_NONE},
  10.         {bone_fpga_init, DEV_ON_BASEBOARD, PROFILE_NONE},//配置相关管脚
  11.         {NULL, 0, 0},
  12. };

  13. static void bone_fpga_init(int evm_id, int profile)
  14. {
  15.         setup_pin_mux(fpga_pin_mux);
  16. }

  17. /* Pin mux for fpga module */
  18. static struct pinmux_config fpga_pin_mux[] = {
  19.         //配置GPMC相关管脚
  20.         //配置GPMC数据端口
  21.         {"gpmc_ad0.gpmc_ad0",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  22.         {"gpmc_ad1.gpmc_ad1",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  23.         {"gpmc_ad2.gpmc_ad2",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  24.         {"gpmc_ad3.gpmc_ad3",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  25.         {"gpmc_ad4.gpmc_ad4",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  26.         {"gpmc_ad5.gpmc_ad5",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  27.         {"gpmc_ad6.gpmc_ad6",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  28.         {"gpmc_ad7.gpmc_ad7",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  29.         {"gpmc_ad8.gpmc_ad8",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  30.         {"gpmc_ad9.gpmc_ad9",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  31.         {"gpmc_ad10.gpmc_ad10",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  32.         {"gpmc_ad11.gpmc_ad11",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  33.         {"gpmc_ad12.gpmc_ad12",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  34.         {"gpmc_ad13.gpmc_ad13",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  35.         {"gpmc_ad14.gpmc_ad14",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  36.         {"gpmc_ad15.gpmc_ad15",          OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  37.         //配置GPMC地址端口
  38.         {"lcd_data0.gpmc_a0",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  39.         {"lcd_data1.gpmc_a1",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  40.         {"lcd_data2.gpmc_a2",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  41.         {"lcd_data3.gpmc_a3",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  42.         {"lcd_data4.gpmc_a4",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  43.         {"lcd_data5.gpmc_a5",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  44.         {"lcd_data6.gpmc_a6",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  45.         {"lcd_data7.gpmc_a7",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  46.         {"lcd_vsync.gpmc_a8",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  47.         {"lcd_hsync.gpmc_a9",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  48.         {"lcd_pclk.gpmc_a10",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  49.         {"lcd_ac_bias_en.gpmc_a11",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  50.         {"lcd_data8.gpmc_a12",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  51. //        {"lcd_data9.gpmc_a13",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  52. //        {"lcd_data10.gpmc_a14",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  53. //        {"lcd_data11.gpmc_a15",     OMAP_MUX_MODE1 | AM33XX_PIN_OUTPUT | AM33XX_PULL_DISA},
  54. //配置GPMC片选管脚,gpmc_csn1作为片选
  55. //        {"gpmc_csn0.gpmc_csn0",          OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
  56. {"gpmc_csn1.gpmc_csn1",          OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
  57. //        {"gpmc_csn2.gpmc_csn2",          OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
  58. //配置GPMC控制管脚
  59. //        {"gpmc_wait0.gpmc_wait0", OMAP_MUX_MODE0 | AM33XX_PIN_INPUT_PULLUP},
  60. //        {"gpmc_wpn.gpmc_wpn",          OMAP_MUX_MODE7 | AM33XX_PIN_INPUT_PULLUP},
  61. //        {"gpmc_advn_ale.gpmc_advn_ale",  OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
  62.         {"gpmc_oen_ren.gpmc_oen_ren",         OMAP_MUX_MODE0 | AM33XX_PULL_DISA},//读
  63.         {"gpmc_wen.gpmc_wen",     OMAP_MUX_MODE0 | AM33XX_PULL_DISA},//写
  64. //        {"gpmc_ben0_cle.gpmc_ben0_cle",         OMAP_MUX_MODE0 | AM33XX_PULL_DISA},
  65.         {"gpmc_clk.gpmc_clk",     OMAP_MUX_MODE0 | AM33XX_PULL_DISA | AM33XX_INPUT_EN},//时钟,AM33XX_INPUT_EN属性一定要加上!!!
  66.         //配置控制DDS芯片AD9832的管脚为GPIO
  67.         {"lcd_data9.gpio2_15", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},//AD9832 SCLK
  68.         {"lcd_data10.gpio2_16", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},//AD9832 SDATA
  69.         {"lcd_data11.gpio2_17", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},//AD9832 FSYNC
  70.         //配置同步数据采集与数据传输的WR_RDN信号管脚及RD_INT_PULSE信号管脚
  71.         {"gpmc_csn0.gpio1_29", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},//RD_INT_PULSE信号是FPGA在采集完一行(512个点)数据后发送的一个正脉冲信号,该正脉冲信号会引起BB发生外部IO中断,从而触发一次读操作!!!
  72. {"gpmc_csn2.gpio1_31", OMAP_MUX_MODE7 | AM33XX_PIN_INPUT},//WDRDN信号是控制采集数据与读数据的信号,在高电平期间FPGA会采集数据并写入缓存,在低电平期间BB会读取缓存数据,这时FPGA不会写缓存,从而有效防止了读写错乱!!!
  73.         {NULL, 0},
  74. };
复制代码
4DDS芯片AD9832驱动及读写FPGAGPMC驱动的实现
4.1DDS芯片AD9832驱动程序
AD9832是ADI公司集成DDS芯片,可以很方便快速地设置输出正弦波的频率,这是本方案实现DDS信号发生器的方法之一,类比基于FPGA的DDS信号发生器,其优点是使用方便,缺点是输出波形单一,应用灵活性差。
驱动源文件为:ddsdev.c
设备驱动文件为:#define DDS_CHIP_DEV "/dev/ddsdev0"
主要功能函数:
6AD9832的读写时序图,dds_byte_shift函数通过GPIO端口模拟了AD9832读写时序,其代码如下:
  1. static void dds_byte_shift(unsigned int data_16)
  2. {
  3.         unsigned int temp;
  4.         gpio_set_value(GPIO_FSYNC, 0);//FSYNC = 0;
  5.         gpio_set_value(GPIO_SCLK, 1);//SCLK = 1;
  6.         udelay(1);

  7.         for (temp = 0x8000; temp != 0; ){
  8.                 if ((data_16 & temp) == 0)//MSB First
  9.                         gpio_set_value(GPIO_SDATA, 0);//SDATA = 0;
  10.                 else
  11.                         gpio_set_value(GPIO_SDATA, 1);//SDATA = 1;

  12.                 udelay(1);//Data setup time
  13.                 gpio_set_value(GPIO_SCLK, 0);//SCLK = 0;
  14.                 temp = temp >> 1;
  15.                 udelay(1);//Data hold time
  16.                 gpio_set_value(GPIO_SCLK, 1);//SCLK=1;
  17.         }

  18.         udelay(1);
  19.         gpio_set_value(GPIO_FSYNC, 1);//FSYNC = 1;

  20.         udelay(1000);
  21. }
复制代码

6AD9832读写时序
函数dds_freq_process及函数dds_freq_adjust用于设置相关控制方式及频率控制字具体含义可以参考AD9832datasheet,并提供两篇CNKI上的论文作为参考:

直接数字频率合成芯片AD9832原理及其典型应用设计【作者】 沈拓 董德存

DDS芯片AD9832的原理及应用【作者】 江玉蓉 周有庆 吴桂清

相关代码如下:
  1. static void dds_freq_process(
  2.         unsigned char freq0_lsbs_l,
  3.         unsigned char freq0_lsbs_h,
  4.         unsigned char freq0_msbs_l,
  5.         unsigned char freq0_msbs_h,
  6.         unsigned char freq1_lsbs_l,
  7.         unsigned char freq1_lsbs_h,
  8.         unsigned char freq1_msbs_l,
  9.         unsigned char freq1_msbs_h
  10.         )
  11. {
  12.         dds_byte_shift(0xd000);        //11 010 00000000000
  13.                                                         //SLEEP RESET CLR

  14.         dds_byte_shift(0x3000 + freq0_lsbs_l);
  15.         dds_byte_shift(0x2100 + freq0_lsbs_h);
  16.         dds_byte_shift(0x3200 + freq0_msbs_l);
  17.         dds_byte_shift(0x2300 + freq0_msbs_h);

  18.         dds_byte_shift(0x3400 + freq1_lsbs_l);
  19.         dds_byte_shift(0x2500 + freq1_lsbs_h);
  20.         dds_byte_shift(0x3600 + freq1_msbs_l);
  21.         dds_byte_shift(0x2700 + freq1_msbs_h);

  22.         dds_byte_shift(0x9000);        //10 01 000000000000
  23.                                                         //SYNC SELSRC

  24.         dds_byte_shift(0xc000);        //11 000 00000000000
  25.                                                         //SLEEP RESET CLR
  26.         
  27.         //dds_byte_shift(0x5555);
  28. }

  29. static void dds_freq_adjust(unsigned long freq_reg0, unsigned long freq_reg1)
  30. {
  31.         unsigned char ll0, lh0, hl0, hh0;
  32.         unsigned char ll1, lh1, hl1, hh1;
  33.         
  34.         printk(KERN_ALERT "Adjust DDS frequency0: %08lx\n", freq_reg0);
  35.         printk(KERN_ALERT "Adjust DDS frequency1: %08lx\n", freq_reg1);
  36.         
  37.         ll0 = (freq_reg0 >> 0) & 0x000000ff;
  38.         lh0 = (freq_reg0 >> 8) & 0x000000ff;
  39.         hl0 = (freq_reg0 >> 16) & 0x000000ff;
  40.         hh0 = (freq_reg0 >> 24) & 0x000000ff;

  41.         ll1 = (freq_reg1 >> 0) & 0x000000ff;
  42.         lh1 = (freq_reg1 >> 8) & 0x000000ff;
  43.         hl1 = (freq_reg1 >> 16) & 0x000000ff;
  44.         hh1 = (freq_reg1 >> 24) & 0x000000ff;

  45.         dds_freq_process(ll0, lh0, hl0, hh0, ll1, lh1, hl1, hh1);
  46. }
复制代码


4.2)读写FPGAGPMC驱动程序

关于读写FPGAGPMC驱动最早之前有过测试,可以看下我之前发的一片帖子:https://bbs.eeworld.com.cn/thread-421181-1-1.html驱动源文件为:fpgadev.c设备驱动文件为:#define DDS_FPGA_DEV    "/dev/fpgadev0"

这里面最关键的几个函数是:

(A)设置GPMC相关寄存器的函数:fpga_gpmc_init对应的释放函数为fpga_gpmc_exit),其关键代码是对6GPMC配置基础的设置,如下标红部分:
  1. static int fpga_gpmc_init(void)
  2. {
  3.         u32 l;
  4.         int ret = -EINVAL;

  5.         gpmc = kmalloc(sizeof(struct gpmc), GFP_KERNEL);
  6.         if (!gpmc){
  7.                 ret = -ENOMEM;
  8.                 goto err_kmalloc;
  9.         }
  10. //        printk(KERN_ALERT "gpmc: %p, gpmc->mem_root: %p, gpmc->cs_mem: %p\n",
  11. //                gpmc, &gpmc->mem_root, gpmc->cs_mem);
  12.         printk(KERN_ALERT "gpmc: %p, gpmc_mem_root: %p, gpmc_cs_mem: %p\n",
  13.                 gpmc, &gpmc_mem_root, gpmc_cs_mem);
  14.         
  15.         gpmc->phys_base = AM33XX_GPMC_BASE;
  16.         gpmc->memsize = AM33XX_GPMC_SIZE;

  17.         if (request_mem_region(gpmc->phys_base,
  18.                 gpmc->memsize, "gpmc") == NULL) {
  19. //        if (request_mem_region(AM33XX_GPMC_BASE,
  20. //                AM33XX_GPMC_SIZE, "gpmc") == NULL) {
  21.                 ret = -ENOMEM;
  22.                 printk(KERN_ALERT "Failed to request memory region\n");
  23.                 goto err_mem;
  24.         }

  25.         gpmc->io_base = ioremap(gpmc->phys_base, gpmc->memsize);
  26. //        gpmc->io_base = ioremap(AM33XX_GPMC_BASE, AM33XX_GPMC_SIZE);
  27.         if (!gpmc->io_base) {
  28.                 ret = -ENOMEM;
  29.                 printk(KERN_ALERT "Failed to ioremap memory\n");
  30.                 goto err_remap;
  31.         }

  32.         printk(KERN_ALERT "GPMC physical base: %08lx, GPMC IO base: %p\n", gpmc->phys_base, gpmc->io_base);
  33. //        printk(KERN_ALERT "GPMC physical base: %08lx, GPMC IO base: %p\n", AM33XX_GPMC_BASE, gpmc->io_base);

  34.         spin_lock_init(&gpmc->mem_lock);

  35.         //Configure GPMC registers
  36.         printk(KERN_ALERT "*****Configure GPMC registers*****\n");

  37.         l = gpmc_read_reg(GPMC_REVISION);
  38.         printk(KERN_ALERT "GPMC revision %d.%d\n", (l >> 4) & 0x0f, l & 0x0f);

  39.         gpmc_write_reg(GPMC_IRQENABLE, 0x0000);//Interrupts are masked
  40.         gpmc_write_reg(GPMC_TIMEOUT_CONTROL, 0x0000);//TimeOut feature is disabled
  41.         
  42.         printk(KERN_ALERT "SYNC_NOR_CONFIG1: %08x\n", SYNC_NOR_CONFIG1);
  43.         printk(KERN_ALERT "SYNC_NOR_CONFIG2: %08x\n", SYNC_NOR_CONFIG2);
  44.         printk(KERN_ALERT "SYNC_NOR_CONFIG3: %08x\n", SYNC_NOR_CONFIG3);
  45.         printk(KERN_ALERT "SYNC_NOR_CONFIG4: %08x\n", SYNC_NOR_CONFIG4);
  46.         printk(KERN_ALERT "SYNC_NOR_CONFIG5: %08x\n", SYNC_NOR_CONFIG5);
  47.         printk(KERN_ALERT "SYNC_NOR_CONFIG6: %08x\n", SYNC_NOR_CONFIG6);
  48.         
  49.         gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG1, SYNC_NOR_CONFIG1);
  50.         gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG2, SYNC_NOR_CONFIG2);
  51.         gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG3, SYNC_NOR_CONFIG3);
  52.         gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG4, SYNC_NOR_CONFIG4);
  53.         gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG5, SYNC_NOR_CONFIG5);
  54.         gpmc_cs_write_reg(GPMC_CS, GPMC_CS_CONFIG6, SYNC_NOR_CONFIG6);
  55.         l = gpmc_cs_read_reg(GPMC_CS, GPMC_CS_CONFIG7);
  56.         printk(KERN_ALERT "Before CS, GPMC_CS_CONFIG7: %08x\n", l);
  57.         
  58.         gpmc_mem_init();

  59.         return 0;

  60.         err_remap:
  61.         release_mem_region(gpmc->phys_base, gpmc->memsize);
  62. //        release_mem_region(AM33XX_GPMC_BASE, AM33XX_GPMC_SIZE);
  63.         err_mem:
  64.                 kfree(gpmc);
  65.         err_kmalloc:
  66.                 return ret;
  67. }
复制代码


6个寄存器的值如何设置需要非常详细地阅读《AM335x ARM ®Cortex™-A8 Microprocessors(MPUs) TechnicalReferenceManual 》文档的7.1 GPMC部分,驱动中给出了这6个寄存器设置值的详细含义说明,如下代码所示:
  1. /* GPMC register offsets */
  2. #define GPMC_REVISION                0x00
  3. #define GPMC_SYSCONFIG                0x10
  4. #define GPMC_SYSSTATUS                0x14
  5. #define GPMC_IRQSTATUS                0x18
  6. #define GPMC_IRQENABLE                0x1c
  7. #define GPMC_TIMEOUT_CONTROL        0x40
  8. #define GPMC_ERR_ADDRESS        0x44
  9. #define GPMC_ERR_TYPE                0x48
  10. #define GPMC_CONFIG                0x50
  11. #define GPMC_STATUS                0x54
  12. #define GPMC_PREFETCH_CONFIG1        0x1e0
  13. #define GPMC_PREFETCH_CONFIG2        0x1e4
  14. #define GPMC_PREFETCH_CONTROL        0x1ec
  15. #define GPMC_PREFETCH_STATUS        0x1f0
  16. #define GPMC_ECC_CONFIG                0x1f4
  17. #define GPMC_ECC_CONTROL        0x1f8
  18. #define GPMC_ECC_SIZE_CONFIG        0x1fc
  19. #define GPMC_ECC1_RESULT        0x200
  20. #define GPMC_ECC_BCH_RESULT_0        0x240

  21. #define GPMC_CS0_OFFSET                0x60
  22. #define GPMC_CS_SIZE                0x30

  23. #define GPMC_MEM_START                0x00000000
  24. #define GPMC_MEM_END                0x3FFFFFFF
  25. #define BOOT_ROM_SPACE                0x100000        /* 1MB */

  26. #define GPMC_CHUNK_SHIFT        24                /* 16 MB */
  27. #define GPMC_SECTION_SHIFT        28                /* 128 MB */

  28. #define CS_NUM_SHIFT                24
  29. #define ENABLE_PREFETCH                (0x1 << 7)
  30. #define DMA_MPU_MODE                2


  31. #define AM33XX_GPMC_BASE        0x50000000
  32. #define AM33XX_GPMC_SIZE SZ_16M
  33. #define GPMC_CS                                1
  34. #define FPGA_SIZE SZ_512


  35. #define GPMCFCLKDIVIDER 0<<0//GPMC_CLK frequency = GPMC_FCLK frequency
  36. #define TIMEPARAGRANULARITY 0<<4//脳1 latencies
  37. #define MUXADDDATA 0<<8//Non-multiplexed attached device
  38. #define DEVICETYPE 0<<10//NOR Flash like, asynchronous and synchronous devices
  39. #define DEVICESIZE 1<<12//16 bit
  40. #define WAITPINSELECT 0<<16//WAIT input pin is WAIT0
  41. #define WAITMONITORINGTIME 0<<18//WAIT pin is monitored with valid data
  42. #define WAITWRITEMONITORING 0<<21//WAIT pin is not monitored for write accesses
  43. #define WAITREADMONITORING 0<<22//WAIT pin is not monitored for read accesses
  44. #define ATTACHEDDEVICEPAGELENGTH 2<<23//Specifies the attached device page (burst) length (1 Word = Interface size), 16Words
  45. #define CLKACTIVATIONTIME 0<<25//First rising edge of GPMC_CLK at start access time
  46. #define WRITETYPE 1<<27//Write Synchronous
  47. #define WRITEMULTIPLE 1<<28//Selects the write single or multiple access, Single access
  48. #define READTYPE 1<<29//Read Synchronous
  49. #define READMULTIPLE 1<<30//Selects the read single or multiple access, Single access
  50. #define WRAPBURST 1<<31//Synchronous wrapping burst not supported

  51. #define SYNC_NOR_CONFIG1                WRAPBURST | \
  52.         READMULTIPLE | READTYPE | WRITEMULTIPLE | WRITETYPE | \
  53.         CLKACTIVATIONTIME | \
  54.         ATTACHEDDEVICEPAGELENGTH | \
  55.         WAITREADMONITORING | WAITWRITEMONITORING | WAITMONITORINGTIME | WAITPINSELECT | \
  56.         DEVICESIZE | DEVICETYPE | MUXADDDATA | \
  57.         TIMEPARAGRANULARITY | GPMCFCLKDIVIDER

  58. #define CSONTIME 1<<0//CS# assertion time from start cycle time, 1 GPMC_FCLK cycle
  59. #define CSEXTRADELAY 0<<7//CS i Timing control signal is not delayed
  60. #define CSRDOFFTIME 15<<8//CS# de-assertion time from start cycle time for read accesses, 15 GPMC_FCLK cycles
  61. #define CSWROFFTIME 15<<16//CS# de-assertion time from start cycle time for write accesses, 15 GPMC_FCLK cycles

  62. #define SYNC_NOR_CONFIG2                CSWROFFTIME | CSRDOFFTIME | CSEXTRADELAY | CSONTIME

  63. #define ADVONTIME 1<<0//ADV# assertion time from start cycle time, 1 GPMC_FCLK cycle
  64. #define ADVAADMUXONTIME 0<<4//ADV# assertion for first address phase when using the AAD-Multiplexed protocol
  65. #define ADVEXTRADELAY 0<<7//ADV Timing control signal is not delayed
  66. #define ADVRDOFFTIME 15<<8//ADV# de-assertion time from start cycle time for read accesses, 15 GPMC_FCLK cycles
  67. #define ADVWROFFTIME 15<<16//ADV# de-assertion time from start cycle time for write accesses, 15 GPMC_FCLK cycles
  68. #define ADVAADMUXRDOFFTIME 0<<24//ADV# de-assertion for first address phase when using the AAD-Mux protocol for read accesses
  69. #define ADVAADMUXWROFFTIME 0<<28//ADV# de-assertion for first address phase when using the AAD-Mux protocol for write accesses

  70. #define SYNC_NOR_CONFIG3                ADVAADMUXWROFFTIME | ADVAADMUXRDOFFTIME | \
  71.         ADVWROFFTIME | ADVRDOFFTIME | ADVEXTRADELAY | ADVAADMUXONTIME | ADVONTIME

  72. #define OEONTIME 1<<0//OE# assertion time from start cycle time
  73. #define OEAADMUXONTIME 0<<4//OE# assertion time for the first address phase in an AAD-Multiplexed access
  74. #define OEEXTRADELAY 0<<7//OE Timing control signal is not delayed
  75. #define OEOFFTIME 15<<8//OE# de-assertion time from start cycle time
  76. #define OEAADMUXOFFTIME 0<<13//OE# de-assertion time for the first address phase in an AAD-Multiplexed access
  77. #define WEONTIME 1<<16//WE# assertion time from start cycle time
  78. #define WEEXTRADELAY 0<<23//WE Timing control signal is not delayed
  79. #define WEOFFTIME 15<<24//WE# de-assertion time from start cycle time

  80. #define SYNC_NOR_CONFIG4                WEOFFTIME | WEEXTRADELAY | WEONTIME | \
  81.         OEAADMUXOFFTIME | OEOFFTIME | OEEXTRADELAY | OEAADMUXONTIME |OEONTIME

  82. #define RDCYCLETIME 15<<0//Total read cycle time
  83. #define WRCYCLETIME 15<<8//Total write cycle time
  84. #define RDACCESSTIME 12<<16//Delay between start cycle time and first data valid
  85. #define PAGEBURSTACCESSTIME 3<<24//Delay between successive words in a multiple access

  86. #define SYNC_NOR_CONFIG5                 PAGEBURSTACCESSTIME | RDACCESSTIME | WRCYCLETIME | RDCYCLETIME

  87. #define BUSTURNAROUND 3<<0//Bus turn around latency between two successive accesses to the same chip-select (read to write) or to a different chip-select (read to read and read to write)
  88. #define CYCLE2CYCLEDIFFCSEN 1<<6//Add Cycle2CycleDelay between two successive accesses to a different chip-select (any access type)
  89. #define CYCLE2CYCLESAMECSEN 1<<7//Add Cycle2CycleDelay between two successive accesses to the same chip-select (any access type)
  90. #define CYCLE2CYCLEDELAY 3<<8//Chip select high pulse delay between two successive accesses
  91. #define WRDATAONADMUXBUS 3<<16//Specifies on which GPMC.FCLK rising edge the first data of the synchronous burst write is driven in the add/data multiplexed bus
  92. #define WRACCESSTIME 12<<24//Delay from StartAccessTime to the GPMC.FCLK rising edge corresponding the the GPMC.CLK rising edge used by the attached memory for the first data capture

  93. #define SYNC_NOR_CONFIG6                WRACCESSTIME | WRDATAONADMUXBUS | \
  94.         CYCLE2CYCLEDELAY | CYCLE2CYCLESAMECSEN | CYCLE2CYCLEDIFFCSEN | \
  95.         BUSTURNAROUND
复制代码

这些设置确实很繁琐,所以真的需要仔细阅读下文档。



(B)!!!用于申请GPMC片选的函数:

gpmc_cs_request(对应的释放函数为gpmc_cs_free)得到申请到的GPMC物理地址空间fpga_phy_basefpga_cs_request(对应的释放函数为fpga_cs_free)根据上述物理地址空间fpga_phy_base最终获得操作GPMC的虚拟地址空间fpga_vir_base


(C)GPMC读写函数:

写函数,在设置FPGADDS波形数据及频率控制字的时候应用层会调用该函数,代码如下:
  1. static ssize_t fpgadev_write(struct file *p_file, const char __user *u_buf, size_t size, loff_t *p_pos)
  2. {

  3.         size_t len = FPGADEV_SIZE;
  4.         int i;
  5.         int tmp;


  6.         struct fpgadev *p_fpgadev = p_file->private_data;

  7.         if (size == 0)
  8.                 return 0;
  9.         if (len > size)
  10.                 len = size;

  11.         memset(p_fpgadev->m_buf, 0, FPGADEV_SIZE);

  12.         if (copy_from_user(p_fpgadev->m_buf, u_buf, len))
  13.                 return -EFAULT;

  14.         for (i=0; i<len; i=i+2)
  15.         {
  16.                 tmp = (p_fpgadev->m_buf[i]) | ((p_fpgadev->m_buf[i+1])<<8);
  17.                 writew(tmp, fpga_vir_base+i);        
  18.                 printk(KERN_ALERT "*****Write*****%p, %04x\n", fpga_vir_base+i, tmp);
  19.         }
  20.         return 0;
  21. }
复制代码
读函数,在数据采集读取采集的数据时会调用该函数,代码如下,特别注意标红加粗的部分:
  1. static ssize_t fpgadev_read(struct file *p_file, char __user *u_buf, size_t size, loff_t *p_pos)
  2. {
  3.         size_t len = FPGADEV_SIZE;
  4.         int i;
  5.         int tmp;
  6.         struct fpgadev *p_fpgadev = p_file->private_data;
  7.         
  8.         if (size == 0)
  9.                 return 0;
  10.         if (len > size)
  11.                 len = size;

  12.         if (*p_pos > 0)
  13.                 return 0;
  14.         
  15.         memset(p_fpgadev->m_buf, 0, FPGADEV_SIZE);

  16.         down(&sync_sema);//wait until read enabled

  17.         for (i=0; i<len; i=i+2)
  18.         {
  19.                 tmp = readw(fpga_vir_base + i);
  20.                 p_fpgadev->m_buf[i] = tmp&0xff;
  21.                 p_fpgadev->m_buf[i+1] = (tmp>>8)&0xff;
  22.                 //printk(KERN_ALERT "*****Read*****%p, %04x\n", fpga_vir_base+i, tmp);
  23.         }
  24.         
  25.         gpio_set_value(GPIO_RSTN, 1);//enable write

  26.         if (copy_to_user(u_buf, p_fpgadev->m_buf, len))
  27.                 return -EFAULT;
  28.         
  29.         return 0;
  30. }
复制代码




sync_sema是一个初值为0的信号量,如果没有数据可读,读函数会进入阻塞状态,在FPGA采集完一行数据后会产生一个RD_INT_PULSE正脉冲信号,该正脉冲信号会引起BB发生外部IO中断,中断处理函数会up sync_sema信号量,从而触发一次读操作,外部中断处理函数会同时清零WDRDN(对应代码中的GPIO_RSTN),使能读缓存失能写缓存,在读函数完成读操作后会置一WDRDN,使能写缓存失能读缓存,WDRDN信号是控制读写数据缓的信号,在高电平期间FPGA将采集的数据写入缓存,在低电平期间BB从缓存中读取数据,这时FPGA不会写缓存,从而保证了读写缓存不会发生错乱。外部中断处理函数代码如下:
  1. static irqreturn_t irq_handler(int irq, void *dev_id)
  2. {
  3.         disable_irq_nosync(irq_no);
  4.         up(&sync_sema);
  5.         gpio_set_value(GPIO_RSTN, 0);//enable read
  6.         enable_irq(irq_no);
  7.         
  8.         return IRQ_HANDLED;
  9. }
复制代码


5BB应用层程序流程如图7所示:
7BB应用程序简易流程图
6)附件2BB端的全部源代码:
附件2DDS_DAQ_BB.rar
6.1其目录树如下所示:

  1. root@gao:~/bone-fs/home/root/DDS_DAQ_BB# tree
  2. .
  3. ├── APP(应用程序)
  4. │   ├── canbus.c
  5. │   ├── canbus.o
  6. │   ├── canconfig.c
  7. │   ├── can_config.h
  8. │   ├── canconfig.o
  9. │   ├── candump.c
  10. │   ├── candump.o
  11. │   ├── cansend.c
  12. │   ├── cansend.o
  13. │   ├── dds.c
  14. │   ├── dds.o
  15. │   ├── ethernet.c
  16. │   ├── ethernet.o
  17. │   ├── libsocketcan.a
  18. │   ├── lscm_debug.h
  19. │   ├── lscm_protocol.h
  20. │   ├── main
  21. │   ├── main.c
  22. │   ├── main.o
  23. │   └── Makefile
  24. ├── board-am335xevm.c(板文件)
  25. ├── DDS_DRV(DDS芯片驱动程序)
  26. │   ├── ddsdev.c
  27. │   ├── ddsdev.ko
  28. │   ├── ddsdev.mod.c
  29. │   ├── ddsdev.mod.o
  30. │   ├── ddsdev.o
  31. │   ├── Makefile
  32. │   ├── modules.order
  33. │   ├── Module.symvers
  34. │   ├── test_ddsdev
  35. │   └── test_ddsdev.c
  36. └── GPMC_DRV(GPMC FPGA驱动程序)
  37.     ├── fpgadev.c
  38.     ├── fpgadev.ko
  39.     ├── fpgadev.mod.c
  40.     ├── fpgadev.mod.o
  41.     ├── fpgadev.o
  42.     ├── Makefile
  43.     ├── modules.order
  44.     ├── Module.symvers
  45.     ├── test_fpgadev
  46.     └── test_fpgadev.c

  47. 3 directories, 41 files
复制代码

6.2BB端源代码的编译过程如下:

A)应用程序编译:
  1. root@gao:~/bone-fs/home/root/DDS_DAQ_BB# ls
  2. APP  board-am335xevm.c  DDS_DRV  GPMC_DRV
  3. root@gao:~/bone-fs/home/root/DDS_DAQ_BB# cd APP
  4. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/APP# ls
  5. canbus.c     can_config.h  cansend.c  ethernet.c      lscm_debug.h     main.c
  6. canconfig.c  candump.c     dds.c      libsocketcan.a  lscm_protocol.h  Makefile
  7. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/APP# make
  8. arm-arago-linux-gnueabi-gcc -c main.c
  9. arm-arago-linux-gnueabi-gcc -c ethernet.c
  10. arm-arago-linux-gnueabi-gcc -c canbus.c
  11. arm-arago-linux-gnueabi-gcc -c dds.c
  12. arm-arago-linux-gnueabi-gcc -c canconfig.c
  13. arm-arago-linux-gnueabi-gcc -c cansend.c
  14. arm-arago-linux-gnueabi-gcc -c candump.c
  15. arm-arago-linux-gnueabi-gcc -o main main.o \
  16.                 ethernet.o canbus.o \
  17.                 dds.o \
  18.                 canconfig.o cansend.o candump.o libsocketcan.a \
  19.                 -lpthread \
  20.                 -lm
复制代码
BGPMC FPGA设备驱动程序编译:
  1. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/APP# cd ../GPMC_DRV/
  2. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/GPMC_DRV# ls
  3. fpgadev.c  Makefile  test_fpgadev.c
  4. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/GPMC_DRV# make
  5. make -C /root/bone-linux M=/root/bone-fs/home/root/DDS_DAQ_BB/GPMC_DRV modules ARCH=arm CROSS_COMPILE=arm-arago-linux-gnueabi-
  6. make[1]: 正在进入目录 `/root/ti-sdk-am335x-evm/board-support/linux-3.2.0-psp04.06.00.08.sdk'
  7.   CC [M]  /root/bone-fs/home/root/DDS_DAQ_BB/GPMC_DRV/fpgadev.o
  8.   Building modules, stage 2.
  9.   MODPOST 1 modules
  10.   CC      /root/bone-fs/home/root/DDS_DAQ_BB/GPMC_DRV/fpgadev.mod.o
  11.   LD [M]  /root/bone-fs/home/root/DDS_DAQ_BB/GPMC_DRV/fpgadev.ko
  12. make[1]:正在离开目录 `/root/ti-sdk-am335x-evm/board-support/linux-3.2.0-psp04.06.00.08.sdk'
  13. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/GPMC_DRV# make app
  14. arm-arago-linux-gnueabi-gcc test_fpgadev.c -o test_fpgadev
复制代码
CDDS芯片驱动程序编译:
  1. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/GPMC_DRV# cd ../DDS_DRV/
  2. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/DDS_DRV# ls
  3. ddsdev.c  Makefile  test_ddsdev.c
  4. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/DDS_DRV# make
  5. make -C /root/bone-linux M=/root/bone-fs/home/root/DDS_DAQ_BB/DDS_DRV modules ARCH=arm CROSS_COMPILE=arm-arago-linux-gnueabi-
  6. make[1]: 正在进入目录 `/root/ti-sdk-am335x-evm/board-support/linux-3.2.0-psp04.06.00.08.sdk'
  7.   CC [M]  /root/bone-fs/home/root/DDS_DAQ_BB/DDS_DRV/ddsdev.o
  8.   Building modules, stage 2.
  9.   MODPOST 1 modules
  10.   CC      /root/bone-fs/home/root/DDS_DAQ_BB/DDS_DRV/ddsdev.mod.o
  11.   LD [M]  /root/bone-fs/home/root/DDS_DAQ_BB/DDS_DRV/ddsdev.ko
  12. make[1]:正在离开目录 `/root/ti-sdk-am335x-evm/board-support/linux-3.2.0-psp04.06.00.08.sdk'
  13. root@gao:~/bone-fs/home/root/DDS_DAQ_BB/DDS_DRV# make app
  14. arm-arago-linux-gnueabi-gcc test_ddsdev.c -o test_ddsdev
复制代码
6.3BB端程序如下执行:
A)挂载开发主机文件系统,开发主机的IP地址为192.168.1.106BBIP地址为192.168.1.2
  1. root@am335x-evm:~# ifconfig eth0
  2. eth0      Link encap:Ethernet  HWaddr D4:94:A1:97:90:BA  
  3.           inet addr:192.168.1.2  Bcast:192.168.1.255  Mask:255.255.255.0
  4.           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
  5.           RX packets:98 errors:0 dropped:40 overruns:0 frame:0
  6.           TX packets:51 errors:0 dropped:0 overruns:0 carrier:0
  7.           collisions:0 txqueuelen:1000
  8.           RX bytes:23520 (22.9 KiB)  TX bytes:4596 (4.4 KiB)

  9. root@am335x-evm:~# ls
  10. fs_mount.sh  tftptest
  11. root@am335x-evm:~# ./fs_mount.sh
  12. mount 192.168.1.106/root/bone-fs /mnt/nfs -o nolock,proto=tcp
  13. Can't set permissions on mtab: Operation not permitted
  14. root@am335x-evm:~# cd /mnt/nfs/home/root/DDS_DAQ_BB/
复制代码
B)加载驱动程序:
  1. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB# ls
  2. APP                DDS_DRV            GPMC_DRV           board-am335xevm.c
  3. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB# cd DDS_DRV/
  4. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB/DDS_DRV# ls
  5. Makefile        ddsdev.ko       ddsdev.o        test_ddsdev.c
  6. Module.symvers  ddsdev.mod.c    modules.order
  7. ddsdev.c        ddsdev.mod.o    test_ddsdev
  8. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB/DDS_DRV# insmod ddsdev.ko
  9. [  231.552669] *****Init*****
  10. [  231.555528] GPIO_SCLK is valid return: 1
  11. [  231.559650] GPIO_SDATA is valid return: 1
  12. [  231.563911] GPIO_FSYNC is valid return: 1
  13. [  231.568135] Request GPIO_SCLK return: 0
  14. [  231.572184] Request GPIO_SDATA return: 0
  15. [  231.576308] Request GPIO_FSYNC return: 0
  16. [  231.580434] GPIO_SCLK set output return: 0
  17. [  231.584881] GPIO_SDATA set output return: 0
  18. [  231.589283] GPIO_FSYNC set output return: 0

  19. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB/DDS_DRV# cd ../GPMC_DRV/
  20. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB/GPMC_DRV# ls
  21. Makefile        fpgadev.ko      fpgadev.o       test_fpgadev.c
  22. Module.symvers  fpgadev.mod.c   modules.order
  23. fpgadev.c       fpgadev.mod.o   test_fpgadev
  24. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB/GPMC_DRV# insmod fpgadev.ko
  25. [  268.803402] *****Init*****
  26. [  268.809626] GPIO_EINT is valid return: 1
  27. [  268.813844] GPIO_RSTN is valid return: 1
  28. [  268.817976] Request GPIO_EINT return: 0
  29. [  268.822024] Request GPIO_RSTN return: 0
  30. [  268.826059] GPIO_RSTN set input return: 0
  31. [  268.830276] GPIO_RSTN set output return: 0
  32. [  268.834599] EINT irq: 221
  33. [  268.837359] Set EINT rising edge return: 0
  34. [  268.841805] Request irq return: 0(0)
  35. [  268.845572] gpmc: cee42680, gpmc_mem_root: bf016624, gpmc_cs_mem: bf016544
  36. [  268.853412] GPMC physical base: 50000000, GPMC IO base: d1000000
  37. [  268.859727] *****Configure GPMC registers*****
  38. [  268.864420] GPMC revision 6.0
  39. [  268.867537] SYNC_NOR_CONFIG1: f9001000
  40. [  268.871476] SYNC_NOR_CONFIG2: 000f0f01
  41. [  268.875428] SYNC_NOR_CONFIG3: 000f0f01
  42. [  268.879367] SYNC_NOR_CONFIG4: 0f010f01
  43. [  268.883339] SYNC_NOR_CONFIG5: 030c0f0f
  44. [  268.887279] SYNC_NOR_CONFIG6: 0c0303c3
  45. [  268.891220] Before CS, GPMC_CS_CONFIG7: 00000f00
  46. [  268.896091] *****Request GPMC CS*****
  47. [  268.899949] Got GPMC CS1, FPGA physical base: 01000000
  48. [  268.905364] After CS, GPMC_CS_CONFIG7: 00000f41
  49. [  268.910149] FPGA virtual base: d087e000
复制代码
C)运行应用程序main可执行文件:
  1. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB/GPMC_DRV# cd ../APP/
  2. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB/APP# ls
  3. Makefile         canconfig.o      dds.c            lscm_debug.h
  4. can_config.h     candump.c        dds.o            lscm_protocol.h
  5. canbus.c         candump.o        ethernet.c       main
  6. canbus.o         cansend.c        ethernet.o       main.c
  7. canconfig.c      cansend.o        libsocketcan.a   main.o
  8. root@am335x-evm:/mnt/nfs/home/root/DDS_DAQ_BB/APP# ./main
  9. this is main function.
  10. socket ok.
  11. bind ok.
  12. listen.
  13. server_bind_listen ok, server_ip: 192.168.1.2, server_port: 5000.
  14. pthread_create ok, thread id: 1086289008.
  15. accept thread is waiting a client to connect......
复制代码
下一篇:BB方案大结局之FPGA端软件实现篇——基于BB及FPGA的DAQ及DDS设计与实现



图6:AD9832读写时序.PNG (47.08 KB, 下载次数: 0)

图6:AD9832读写时序

图6:AD9832读写时序

图7:BB应用程序简易流程图.PNG (89.64 KB, 下载次数: 0)

图7:BB应用程序简易流程图

图7:BB应用程序简易流程图

附件2:DDS_DAQ_BB.rar

184.13 KB, 下载次数: 29

附件2:DDS_DAQ_BB

点赞 关注
 

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

查找数据手册?

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
快速回复 返回顶部 返回列表