切换到宽版
  • 20837阅读
  • 71回复

[ARM]GD32逻辑分析仪最终版,23M、10M、3M、1M、300K、100k5档采样速率60k存储深度端口捕捉 [复制链接]

上一主题 下一主题
离线huaweiwx
 

发帖
1372
M币
2167
专家
65
粉丝
297
只看楼主 倒序阅读 我要置顶 楼主  发表于: 2016-06-15
挖尽GD32潜力,做逻辑分析仪,15M采样速率,60k存储深度,体现GD优越性:http://bbs.mydigit.cn/read.php?tid=1589478
挖尽GD32潜力,做逻辑分析仪(续),采样速率提高至23M,60k存储深度,真正体现GD优越性:http://bbs.mydigit.cn/read.php?tid=1696568


   2545889167   jpdd521   等坛友建议增加触发条件的捕捉,顺便也将在单一采样速率23M基础上增加了10M 3M 1M 300K 100K六档可选,并可按相应上位机的捕捉条件 端口通道选择 MASK 和对应的值 MASKVALUE 来触发取样,每个取样速率的时间也经过精确校正,最后奉献给喜欢的坛友玩玩,在此基础上还可扩充其它的功能如外部触发、延时触发等特定要求,源程序如下:
  1. /*
  2.    SLLogicLogger - Simple logic analyser for Stellaris Launchpad
  3.    SLLogicLogger supports the SUMP protocol over UART. The UART is mapped
  4.    through the debug/flash controller on the Stellaris Launchpad to a virtual
  5.    com port. It samples signals on PORTB with samplerate 10 Mhz, buffersize
  6.    16kByte, sampling starts at any change on PORTB[0..7].
  7.    PB0 and PB1 are limited to 3.6 V! All other pins are 5 V tolerant.
  8.    The idea for this simple analyser comes from http://jjmz.free.fr/?p=148
  9.    Description of the SUMP protocol:
  10.    - http://www.sump.org/projects/analyzer/protocol/
  11.    - http://dangerousprototypes.com/docs/The_Logic_Sniffer%27s_extended_SUMP_protocol
  12.    A multiplatform client which supports the SUMP protocol is OLS:
  13.    http://www.lxtreme.nl/ols/
  14.    To install device support for OLS, copy ols.profile* file into the
  15.    ols/plugins folder.
  16.    Copyright (C) 2012 Thomas Fischl <tfischl@gmx.de> http://www.fischl.de
  17.    Last update: 2012-12-24
  18.    for gd32f103ret6 120M f_cpu samples signals on PORTA(0..7) with samplerate 23 Mhz, buffersize
  19.    60kByte. by huaweiwx@sina.com 2016.6.12
  20.    add samplerate 10M 3M 1M 300M 100K and trigger 2016.6.15
  21. */
  22. //profile:  device.metadata.keys= "SLLogicLogger"
  23. #define DEVICE  "SLLogicLogger"
  24. #define VERSION "0.11"
  25. //boards
  26. #define LED  LED_BUILTIN  //LED_BUILTIN
  27. // buffer size
  28. #define MAX_CAPTURE_SIZE 60*1024
  29. #define MAX_SAMPLERATE  22800000
  30. // input port read regaddress & pins_arry
  31. #define GPIO_PORT_DATA_R GPIOA->regs->IDR
  32. uint8_t pin[8] = {PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7};
  33. // SUMP command defintions
  34. #define SUMP_RESET 0x00
  35. #define SUMP_ARM   0x01
  36. #define SUMP_QUERY 0x02
  37. #define SUMP_SELF_TEST 0x03
  38. #define SUMP_GET_METADATA 0x04
  39. #define SUMP_XON   0x11
  40. #define SUMP_XOFF  0x13
  41. #define SUMP_TRIGGER_MASK   0xC0
  42. #define SUMP_TRIGGER_VALUES 0xC1
  43. #define SUMP_TRIGGER_CONFIG 0xC2
  44. /* Most flags (except RLE) are ignored. */
  45. #define SUMP_SET_DIVIDER 0x80
  46. #define SUMP_SET_READ_DELAY_COUNT 0x81
  47. #define SUMP_SET_FLAGS 0x82
  48. #define SUMP_SET_RLE 0x0100
  49. //vars
  50. uint8_t        cmdByte = 0;
  51. uint8_t        trigger = 0;
  52. uint8_t trigger_values = 0;
  53. uint8_t  cmdBytes[5];
  54. uint32_t       divider = 3;
  55. uint8_t  useMicro = 0;
  56. uint8_t  rleEnabled = false;
  57. uint16_t readCount = MAX_CAPTURE_SIZE;
  58. uint16_t delayCount = 0;
  59. uint32_t tus;
  60. // sampling buffer
  61. uint8_t logicdata[MAX_CAPTURE_SIZE + 1];
  62. volatile uint32_t delays;
  63. // send 32bit unsigned integer as SUMP metadata
  64. void sump_sendmeta_uint32(uint8_t type, uint32_t i) {
  65.   Serial1.write(type);
  66.   Serial1.write((i >> 24) & 0xff);
  67.   Serial1.write((i >> 16) & 0xff);
  68.   Serial1.write((i >> 8)  & 0xff);
  69.   Serial1.write(i & 0xff);
  70. }
  71. // send 8bit unsigned integer as SUMP metadata
  72. void sump_sendmeta_uint8(uint8_t type, uint8_t i) {
  73.   Serial1.write(type);
  74.   Serial1.write(i);
  75. }
  76. /*
  77.    Extended SUMP commands are 5 bytes.  A command byte followed by 4 bytes
  78.    of options. We already read the command byte, this gets the remaining
  79.    4 bytes of the command.
  80.    If we're debugging we save the received commands in a debug buffer.
  81.    We need to make sure we don't overrun the debug buffer.
  82. */
  83. void getCmd() {
  84.   delay(10);
  85.   cmdBytes[0] = Serial1.read();
  86.   cmdBytes[1] = Serial1.read();
  87.   cmdBytes[2] = Serial1.read();
  88.   cmdBytes[3] = Serial1.read();
  89. }
  90. //100ns delay
  91. static inline __always_inline void delay100ns(volatile uint32_t nsk) {
  92.   for (; nsk != 0; nsk--);
  93. }
  94. /*
  95.    This function calculates what delay we need for the specific sample rate.
  96.    The dividers are based on SUMP's 100Mhz clock.
  97.    For example, a 1MHz sample rate has a divider of 99 (0x63 in the command
  98.    byte).
  99.    rate = clock / (divider + 1)
  100.    rate = 100,000,000 / (99 + 1)
  101.    result is 1,000,000 saying we want a 1MHz sample rate.
  102.    We calculate our inter sample delay from the divider and the delay between
  103.    samples gives us the sample rate per second.
  104.    So for 1MHz, delay = (99 + 1) / 100 which gives us a 1 microsecond delay.
  105.    For 500KHz, delay = (199 + 1) / 100 which gives us a 2 microsecond delay.
  106. */
  107. void setupDelay() {
  108.   if (divider < 9) { //9+1 = 10M
  109.     useMicro = 0;
  110.   }
  111.   else {            //  <10M
  112.     useMicro = 1;
  113.   }
  114.   switch (divider) {
  115.     case 999:  //100k
  116.       delays = 295;
  117.       break;
  118.     case 332:  //300k
  119.       delays = 95;
  120.       break;
  121.     case 99: // 100/(99+1) = 1M
  122.       delays = 25;
  123.       break;
  124.     case 32: // 3M
  125.       delays = 5;
  126.       break;
  127. }
  128. }
  129. // wait for trigger and do sampling
  130. void dosampling() {
  131.   uint32_t i = 0x2fffffff;
  132.   volatile uint32_t *port = &GPIO_PORT_DATA_R;
  133.   uint8_t v = GPIO_PORT_DATA_R;
  134.   uint32_t start;
  135.   // get current gpio state an wait for change or timeout
  136.   if (trigger) {
  137.     while ((trigger_values ^ (GPIO_PORT_DATA_R)) & trigger);
  138.   } else {
  139.     while ((i-- != 0) && (GPIO_PORT_DATA_R == v));
  140.   }
  141.   i = MAX_CAPTURE_SIZE;
  142.   digitalWrite(LED, LOW);  //for lowplus check
  143.   start = micros();
  144.   switch (divider) {
  145.     case 3:   //100m/23m -1 =3
  146.       systick_disable(); //2680us
  147.       do {
  148.         logicdata[i--] = *port; //1
  149.         logicdata[i--] = *port; //2
  150.         logicdata[i--] = *port; //3
  151.         logicdata[i--] = *port; //4
  152.         logicdata[i--] = *port; //5
  153.         logicdata[i--] = *port; //6
  154.         logicdata[i--] = *port; //7
  155.         logicdata[i--] = *port; //8
  156.         logicdata[i--] = *port; //9
  157.         logicdata[i--] = *port; //10
  158.         logicdata[i--] = *port; //11
  159.         logicdata[i--] = *port; //12
  160.         logicdata[i--] = *port; //13
  161.         logicdata[i--] = *port; //14
  162.         logicdata[i--] = *port; //15
  163.         logicdata[i--] = *port; //16
  164.         logicdata[i--] = *port; //17
  165.         logicdata[i--] = *port; //18
  166.         logicdata[i--] = *port; //19
  167.         logicdata[i--] = *port; //20
  168.       } while (i);  //60/20=3*1024 cicules speed 23M
  169.       systick_enable();
  170.       break;
  171.     case 9: // 100/(9+1) = 10M
  172.       do {
  173.         asm volatile("nop");
  174.         asm volatile("nop");
  175.         logicdata[i--] = *port;  //1
  176.       } while (i);
  177.       break;
  178.     default:
  179.       do {
  180.         asm volatile("nop");
  181.         delay100ns(delays);
  182.         logicdata[i--] = *port;  //1
  183.       } while (i);
  184.       break;
  185.   }
  186.   tus = micros() - start;
  187.   digitalWrite(LED, HIGH);
  188.   // send it over uart
  189.   for (i = MAX_CAPTURE_SIZE; i != 0; i--) Serial1.write(logicdata[i]); //output unsigned char 8bit data
  190. }
  191. //init
  192. void setup() {
  193.   pinMode(LED, OUTPUT);
  194.   for (uint32_t i = 0; i < 8; i++) pinMode(pin[i], INPUT); //for sample input
  195.   Serial1.begin(115200);
  196.   for (uint32_t i = 0; i < 7; i++) { //ready blink 3 times
  197.     digitalToggle(LED);
  198.     delay(250);
  199.   }
  200. }
  201. // main routine
  202. void loop () {
  203.   if (Serial1.available()) {
  204.     // get the new byte:
  205.     cmdByte = Serial1.read();
  206.     switch (cmdByte) {
  207.       case SUMP_RESET: //0x00
  208.       case     SUMP_SELF_TEST: //0x03
  209.         break;
  210.       case SUMP_ARM:   //0x01
  211.         dosampling();
  212.         break;
  213.       case SUMP_QUERY: //0x02
  214.         //        Serial1.print("1ALS");
  215.         Serial1.write('1');
  216.         Serial1.write('A');
  217.         Serial1.write('L');
  218.         Serial1.write('S');
  219.         break;
  220.       case SUMP_GET_METADATA: //0x04
  221.         // device type SLLogicLogger
  222.         Serial1.write((uint8_t)0x01);
  223.         Serial1.print(DEVICE);  //  "SLLogicLogger1.0"
  224.         Serial1.write((uint8_t)0x00);
  225.         /* FPGA firmware version */
  226.         Serial1.write((uint8_t)0x02);
  227.         Serial1.print(VERSION);  //  "0.11"
  228.         Serial1.write((uint8_t)0x00);
  229.         // amount of sample memory available (bytes)
  230.         sump_sendmeta_uint32(0x21, MAX_CAPTURE_SIZE);
  231.         // maximum sample rate (hz)
  232.         sump_sendmeta_uint32(0x23, MAX_SAMPLERATE);
  233.         //0x25 Capability Flags 0x0000001F
  234.         //Bit 0 - Basic Trigger available.
  235.         //Bit 1 - Advanced Trigger available.
  236.         //Bit 2 - RLE Encoding available (see flag register).
  237.         //Bit 3 - Extra RLE Encoding modes available (see flag register).
  238.         //Bit 4 - State capture mode available (see flag register)
  239.         //Bit 5 - Finish Now command available.
  240.         //Bit 6 - Query Input Data command available.
  241.         //Bit 7 - Query Capture State command available.
  242.         //Bit 8 - Return Capture Data command, and manual capture mode available (see flag register).
  243.         //Bits 31 - 9 - reserved
  244.         sump_sendmeta_uint32(0x25, 0x000000003);
  245.         // number of usable probes (short)
  246.         sump_sendmeta_uint8(0x40, 0x08);
  247.         // protocol version (short)
  248.         sump_sendmeta_uint8(0x41, 0x02);
  249.         // end of meta data
  250.         Serial1.write((uint8_t)0x00);
  251.         break;
  252.       // long commands.. consume bytes from uart
  253.       case SUMP_TRIGGER_MASK:  //0xc0
  254.       case 0xC4:
  255.       case 0xC8:
  256.       case 0xCC:
  257.         getCmd();
  258.         trigger = cmdBytes[0];
  259.         break;
  260.       case SUMP_TRIGGER_VALUES:  //0xc1
  261.       case 0xC5:
  262.       case 0xC9:
  263.       case 0xCD:
  264.         /*
  265.              trigger_values can be used directly as the value of each bit
  266.            defines whether we're looking for it to be high or low.
  267.         */
  268.         getCmd();
  269.         trigger_values = cmdBytes[0];
  270.         break;
  271.       case SUMP_TRIGGER_CONFIG://c2
  272.       case 0xC6:
  273.       case 0xCA:
  274.       case 0xCE:
  275.         /* read the rest of the command bytes, but ignore them. */
  276.         getCmd();
  277.         break;
  278.       case SUMP_SET_DIVIDER:   //0x80
  279.         /*
  280.              the shifting needs to be done on the 32bit unsigned long variable
  281.            so that << 16 doesn't end up as zero.
  282.         */
  283.         getCmd();
  284.         divider = cmdBytes[2];
  285.         divider = divider << 8;
  286.         divider += cmdBytes[1];
  287.         divider = divider << 8;
  288.         divider += cmdBytes[0];
  289.         setupDelay();
  290.         break;
  291.       case SUMP_SET_READ_DELAY_COUNT://0x81:
  292.         /*
  293.              this just sets up how many samples there should be before
  294.            and after the trigger fires.  The readCount is total samples
  295.            to return and delayCount number of samples after the trigger.
  296.            this sets the buffer splits like 0/100, 25/75, 50/50
  297.            for example if readCount == delayCount then we should
  298.            return all samples starting from the trigger point.
  299.            if delayCount < readCount we return (readCount - delayCount) of
  300.            samples from before the trigger fired.
  301.         */
  302.         getCmd();
  303.         readCount = 4 * (((cmdBytes[1] << 8) | cmdBytes[0]) + 1);
  304.         if (readCount > MAX_CAPTURE_SIZE)
  305.           readCount = MAX_CAPTURE_SIZE;
  306.         delayCount = 4 * (((cmdBytes[3] << 8) | cmdBytes[2]) + 1);
  307.         if (delayCount > MAX_CAPTURE_SIZE)
  308.           delayCount = MAX_CAPTURE_SIZE;
  309.         break;
  310.       case SUMP_SET_FLAGS: //0x82
  311.         /* read the rest of the command bytes and check if RLE is enabled. */
  312.         getCmd();
  313.         rleEnabled = ((cmdBytes[1] & B1000000) != 0);
  314.         break;
  315. /*      case '?':  //debug dump vars
  316.         Serial1.print("divider: 0x");  Serial1.println(divider, HEX);
  317.         Serial1.print("trigger_values: 0x");  Serial1.println(trigger_values, BIN);
  318.         Serial1.print("readCount: ");   Serial1.println(readCount, DEC);
  319.         Serial1.print("delayCount: "); Serial1.println(delayCount, DEC);
  320.         Serial1.print("trigger: ");    Serial1.println(trigger, DEC);
  321.         Serial1.print("useMicro: ");   Serial1.println(useMicro, DEC);
  322.         Serial1.print("rleEnabled: ");   Serial1.println(rleEnabled, DEC);
  323.         Serial1.print("sample time us="); Serial1.println(tus, DEC);
  324.         Serial1.print("delays ");Serial1.println(delays,DEC);
  325.         Serial1.print("divider ");Serial1.println(divider,DEC);
  326.        break;*/
  327.       default:
  328.         break;
  329.     }
  330.   }
  331. }

相应的配置文件:
  1. # Configuration for SLLogicLogger
  2. # The short (single word) type of the device described in this profile
  3. device.type = SLLogicLogger
  4. # A longer description of the device
  5. device.description = SLLogicLogger (GD32F103RET6)
  6. # The device interface, SERIAL only
  7. device.interface = SERIAL
  8. # The device's native clockspeed, in Hertz.
  9. device.clockspeed = 120000000
  10. # Whether or not double-data-rate is supported by the device (also known as the "demux"-mode).
  11. device.supports_ddr = false
  12. # Supported sample rates in Hertz, separated by comma's
  13. device.samplerates =  22800000,10000000,3000000,1000000,300000,100000
  14. # The clockspeed used in the divider calculation, in Hertz. Defaults to 100MHz as most devices appear to use this.
  15. device.dividerClockspeed = 100000000
  16. # What capture clocks are supported
  17. device.captureclock = INTERNAL
  18. # The supported capture sizes, in bytes
  19. device.capturesizes = 61440
  20. # Whether or not the noise filter is supported
  21. device.feature.noisefilter = false
  22. # Whether or not Run-Length encoding is supported
  23. device.feature.rle = false
  24. # Whether or not a testing mode is supported
  25. device.feature.testmode = false
  26. # Whether or not triggers are supported
  27. device.feature.triggers = true
  28. # The number of trigger stages
  29. device.trigger.stages = 1
  30. # Whether or not "complex" triggers are supported
  31. device.trigger.complex = false
  32. # The total number of channels usable for capturing
  33. device.channel.count = 8
  34. # The number of channels groups, together with the channel count determines the channels per group
  35. device.channel.groups = 1
  36. # Whether the capture size is limited by the enabled channel groups
  37. device.capturesize.bound = false
  38. # Which numbering does the device support
  39. device.channel.numberingschemes = INSIDE, OUTSIDE
  40. # Is a delay after opening the port and device detection needed? (0 = no delay, >0 = delay in milliseconds)
  41. device.open.portdelay = 0
  42. # The receive timeout for the device (in milliseconds, 100 = default, <=0 = no timeout)
  43. device.receive.timeout = 100
  44. # Does the device need a high or low DTR-line to operate correctly? (high = true, low = false)
  45. device.open.portdtr = false
  46. # Which metadata keys correspond to this device profile? Value is a comma-separated list of (double quoted) names...
  47. device.metadata.keys = "SLLogicLogger"
  48. # In which order are samples sent back from the device? false = last sample first, true = first sample first
  49. device.samples.reverseOrder = true
  50. ###EOF###
全部文件:




[ 此帖被huaweiwx在2016-06-19 16:45重新编辑 ]
本文内容包含图片或附件,获取更多资讯,请 登录 后查看;或者 注册 成为会员获得更多权限
本帖最近打赏记录:共17条打赏M币+93
12
离线jpdd521

发帖
25694
M币
7956
专家
15
粉丝
350
只看该作者 1楼 发表于: 2016-06-15
请登录后查看
本帖最近打赏记录:共1条打赏M币+3
离线xktx09

发帖
4992
M币
3889
专家
2
粉丝
126
只看该作者 2楼 发表于: 2016-06-15
请登录后查看
本帖最近打赏记录:共1条打赏M币+3
离线mindlwj
发帖
47
M币
-370
专家
0
粉丝
2
只看该作者 3楼 发表于: 2016-06-15
Re:GD32逻辑分析仪最终版,23M、10M、3M、1M、300K、100k5档采样速率60k存储深度端 ..
请登录后查看
本帖最近打赏记录:共1条打赏M币+3
离线sanzs

发帖
2172
M币
2665
专家
0
粉丝
11
只看该作者 4楼 发表于: 2016-06-15
Re:GD32逻辑分析仪最终版,23M、10M、3M、1M、300K、100k5档采样速率60k存储深度端 ..
请登录后查看
本帖最近打赏记录:共1条打赏M币+3
离线chenlei1910

发帖
11032
M币
1444
专家
2
粉丝
40
只看该作者 5楼 发表于: 2016-06-15
请登录后查看
本帖最近打赏记录:共1条打赏M币+3
离线2545889167

发帖
13268
M币
20754
专家
302
粉丝
4860
只看该作者 6楼 发表于: 2016-06-15
请登录后查看
离线2545889167

发帖
13268
M币
20754
专家
302
粉丝
4860
只看该作者 7楼 发表于: 2016-06-15
Re:GD32逻辑分析仪最终版,23M、10M、3M、1M、300K、100k5档采样速率60k存储深度端 ..
请登录后查看
本帖最近打赏记录:共2条打赏M币+6
离线2545889167

发帖
13268
M币
20754
专家
302
粉丝
4860
只看该作者 8楼 发表于: 2016-06-15
Re:GD32逻辑分析仪最终版,23M、10M、3M、1M、300K、100k5档采样速率60k存储深度端 ..
请登录后查看
离线huaweiwx

发帖
1372
M币
2167
专家
65
粉丝
297
只看该作者 9楼 发表于: 2016-06-15
回 2545889167 的帖子
请登录后查看
[ 此帖被huaweiwx在2016-06-15 17:53重新编辑 ]
本帖最近打赏记录:共3条打赏M币+19
快速回复
限80 字节
温馨提示:欢迎交流讨论,请勿发布纯表情、纯引用等灌水帖子;以免被删除
 
上一个 下一个