
-
UID:1023450
-
- 注册时间2011-12-16
- 最后登录2022-04-17
- 在线时间2350小时
-
-
访问TA的空间加好友用道具
|
挖尽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 来触发取样,每个取样速率的时间也经过精确校正,最后奉献给喜欢的坛友玩玩,在此基础上还可扩充其它的功能如外部触发、延时触发等特定要求,源程序如下:- /*
- SLLogicLogger - Simple logic analyser for Stellaris Launchpad
- SLLogicLogger supports the SUMP protocol over UART. The UART is mapped
- through the debug/flash controller on the Stellaris Launchpad to a virtual
- com port. It samples signals on PORTB with samplerate 10 Mhz, buffersize
- 16kByte, sampling starts at any change on PORTB[0..7].
- PB0 and PB1 are limited to 3.6 V! All other pins are 5 V tolerant.
- The idea for this simple analyser comes from http://jjmz.free.fr/?p=148
- Description of the SUMP protocol:
- - http://www.sump.org/projects/analyzer/protocol/
- - http://dangerousprototypes.com/docs/The_Logic_Sniffer%27s_extended_SUMP_protocol
- A multiplatform client which supports the SUMP protocol is OLS:
- http://www.lxtreme.nl/ols/
- To install device support for OLS, copy ols.profile* file into the
- ols/plugins folder.
- Copyright (C) 2012 Thomas Fischl <tfischl@gmx.de> http://www.fischl.de
- Last update: 2012-12-24
- for gd32f103ret6 120M f_cpu samples signals on PORTA(0..7) with samplerate 23 Mhz, buffersize
- 60kByte. by huaweiwx@sina.com 2016.6.12
- add samplerate 10M 3M 1M 300M 100K and trigger 2016.6.15
- */
- //profile: device.metadata.keys= "SLLogicLogger"
- #define DEVICE "SLLogicLogger"
- #define VERSION "0.11"
- //boards
- #define LED LED_BUILTIN //LED_BUILTIN
- // buffer size
- #define MAX_CAPTURE_SIZE 60*1024
- #define MAX_SAMPLERATE 22800000
- // input port read regaddress & pins_arry
- #define GPIO_PORT_DATA_R GPIOA->regs->IDR
- uint8_t pin[8] = {PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7};
- // SUMP command defintions
- #define SUMP_RESET 0x00
- #define SUMP_ARM 0x01
- #define SUMP_QUERY 0x02
- #define SUMP_SELF_TEST 0x03
- #define SUMP_GET_METADATA 0x04
- #define SUMP_XON 0x11
- #define SUMP_XOFF 0x13
- #define SUMP_TRIGGER_MASK 0xC0
- #define SUMP_TRIGGER_VALUES 0xC1
- #define SUMP_TRIGGER_CONFIG 0xC2
- /* Most flags (except RLE) are ignored. */
- #define SUMP_SET_DIVIDER 0x80
- #define SUMP_SET_READ_DELAY_COUNT 0x81
- #define SUMP_SET_FLAGS 0x82
- #define SUMP_SET_RLE 0x0100
- //vars
- uint8_t cmdByte = 0;
- uint8_t trigger = 0;
- uint8_t trigger_values = 0;
- uint8_t cmdBytes[5];
- uint32_t divider = 3;
- uint8_t useMicro = 0;
- uint8_t rleEnabled = false;
- uint16_t readCount = MAX_CAPTURE_SIZE;
- uint16_t delayCount = 0;
- uint32_t tus;
- // sampling buffer
- uint8_t logicdata[MAX_CAPTURE_SIZE + 1];
- volatile uint32_t delays;
- // send 32bit unsigned integer as SUMP metadata
- void sump_sendmeta_uint32(uint8_t type, uint32_t i) {
- Serial1.write(type);
- Serial1.write((i >> 24) & 0xff);
- Serial1.write((i >> 16) & 0xff);
- Serial1.write((i >> 8) & 0xff);
- Serial1.write(i & 0xff);
- }
- // send 8bit unsigned integer as SUMP metadata
- void sump_sendmeta_uint8(uint8_t type, uint8_t i) {
- Serial1.write(type);
- Serial1.write(i);
- }
- /*
- Extended SUMP commands are 5 bytes. A command byte followed by 4 bytes
- of options. We already read the command byte, this gets the remaining
- 4 bytes of the command.
- If we're debugging we save the received commands in a debug buffer.
- We need to make sure we don't overrun the debug buffer.
- */
- void getCmd() {
- delay(10);
- cmdBytes[0] = Serial1.read();
- cmdBytes[1] = Serial1.read();
- cmdBytes[2] = Serial1.read();
- cmdBytes[3] = Serial1.read();
- }
- //100ns delay
- static inline __always_inline void delay100ns(volatile uint32_t nsk) {
- for (; nsk != 0; nsk--);
- }
- /*
- This function calculates what delay we need for the specific sample rate.
- The dividers are based on SUMP's 100Mhz clock.
- For example, a 1MHz sample rate has a divider of 99 (0x63 in the command
- byte).
- rate = clock / (divider + 1)
- rate = 100,000,000 / (99 + 1)
- result is 1,000,000 saying we want a 1MHz sample rate.
- We calculate our inter sample delay from the divider and the delay between
- samples gives us the sample rate per second.
- So for 1MHz, delay = (99 + 1) / 100 which gives us a 1 microsecond delay.
- For 500KHz, delay = (199 + 1) / 100 which gives us a 2 microsecond delay.
- */
- void setupDelay() {
- if (divider < 9) { //9+1 = 10M
- useMicro = 0;
- }
- else { // <10M
- useMicro = 1;
- }
- switch (divider) {
- case 999: //100k
- delays = 295;
- break;
- case 332: //300k
- delays = 95;
- break;
- case 99: // 100/(99+1) = 1M
- delays = 25;
- break;
- case 32: // 3M
- delays = 5;
- break;
- }
- }
- // wait for trigger and do sampling
- void dosampling() {
- uint32_t i = 0x2fffffff;
- volatile uint32_t *port = &GPIO_PORT_DATA_R;
- uint8_t v = GPIO_PORT_DATA_R;
- uint32_t start;
- // get current gpio state an wait for change or timeout
- if (trigger) {
- while ((trigger_values ^ (GPIO_PORT_DATA_R)) & trigger);
- } else {
- while ((i-- != 0) && (GPIO_PORT_DATA_R == v));
- }
- i = MAX_CAPTURE_SIZE;
- digitalWrite(LED, LOW); //for lowplus check
- start = micros();
- switch (divider) {
- case 3: //100m/23m -1 =3
- systick_disable(); //2680us
- do {
- logicdata[i--] = *port; //1
- logicdata[i--] = *port; //2
- logicdata[i--] = *port; //3
- logicdata[i--] = *port; //4
- logicdata[i--] = *port; //5
- logicdata[i--] = *port; //6
- logicdata[i--] = *port; //7
- logicdata[i--] = *port; //8
- logicdata[i--] = *port; //9
- logicdata[i--] = *port; //10
- logicdata[i--] = *port; //11
- logicdata[i--] = *port; //12
- logicdata[i--] = *port; //13
- logicdata[i--] = *port; //14
- logicdata[i--] = *port; //15
- logicdata[i--] = *port; //16
- logicdata[i--] = *port; //17
- logicdata[i--] = *port; //18
- logicdata[i--] = *port; //19
- logicdata[i--] = *port; //20
- } while (i); //60/20=3*1024 cicules speed 23M
- systick_enable();
- break;
- case 9: // 100/(9+1) = 10M
- do {
- asm volatile("nop");
- asm volatile("nop");
- logicdata[i--] = *port; //1
- } while (i);
- break;
- default:
- do {
- asm volatile("nop");
- delay100ns(delays);
- logicdata[i--] = *port; //1
- } while (i);
- break;
- }
- tus = micros() - start;
- digitalWrite(LED, HIGH);
- // send it over uart
- for (i = MAX_CAPTURE_SIZE; i != 0; i--) Serial1.write(logicdata[i]); //output unsigned char 8bit data
- }
- //init
- void setup() {
- pinMode(LED, OUTPUT);
- for (uint32_t i = 0; i < 8; i++) pinMode(pin[i], INPUT); //for sample input
- Serial1.begin(115200);
- for (uint32_t i = 0; i < 7; i++) { //ready blink 3 times
- digitalToggle(LED);
- delay(250);
- }
- }
- // main routine
- void loop () {
- if (Serial1.available()) {
- // get the new byte:
- cmdByte = Serial1.read();
- switch (cmdByte) {
- case SUMP_RESET: //0x00
- case SUMP_SELF_TEST: //0x03
- break;
- case SUMP_ARM: //0x01
- dosampling();
- break;
- case SUMP_QUERY: //0x02
- // Serial1.print("1ALS");
- Serial1.write('1');
- Serial1.write('A');
- Serial1.write('L');
- Serial1.write('S');
- break;
- case SUMP_GET_METADATA: //0x04
- // device type SLLogicLogger
- Serial1.write((uint8_t)0x01);
- Serial1.print(DEVICE); // "SLLogicLogger1.0"
- Serial1.write((uint8_t)0x00);
- /* FPGA firmware version */
- Serial1.write((uint8_t)0x02);
- Serial1.print(VERSION); // "0.11"
- Serial1.write((uint8_t)0x00);
- // amount of sample memory available (bytes)
- sump_sendmeta_uint32(0x21, MAX_CAPTURE_SIZE);
- // maximum sample rate (hz)
- sump_sendmeta_uint32(0x23, MAX_SAMPLERATE);
- //0x25 Capability Flags 0x0000001F
- //Bit 0 - Basic Trigger available.
- //Bit 1 - Advanced Trigger available.
- //Bit 2 - RLE Encoding available (see flag register).
- //Bit 3 - Extra RLE Encoding modes available (see flag register).
- //Bit 4 - State capture mode available (see flag register)
- //Bit 5 - Finish Now command available.
- //Bit 6 - Query Input Data command available.
- //Bit 7 - Query Capture State command available.
- //Bit 8 - Return Capture Data command, and manual capture mode available (see flag register).
- //Bits 31 - 9 - reserved
- sump_sendmeta_uint32(0x25, 0x000000003);
- // number of usable probes (short)
- sump_sendmeta_uint8(0x40, 0x08);
- // protocol version (short)
- sump_sendmeta_uint8(0x41, 0x02);
- // end of meta data
- Serial1.write((uint8_t)0x00);
- break;
- // long commands.. consume bytes from uart
- case SUMP_TRIGGER_MASK: //0xc0
- case 0xC4:
- case 0xC8:
- case 0xCC:
- getCmd();
- trigger = cmdBytes[0];
- break;
- case SUMP_TRIGGER_VALUES: //0xc1
- case 0xC5:
- case 0xC9:
- case 0xCD:
- /*
- trigger_values can be used directly as the value of each bit
- defines whether we're looking for it to be high or low.
- */
- getCmd();
- trigger_values = cmdBytes[0];
- break;
- case SUMP_TRIGGER_CONFIG://c2
- case 0xC6:
- case 0xCA:
- case 0xCE:
- /* read the rest of the command bytes, but ignore them. */
- getCmd();
- break;
- case SUMP_SET_DIVIDER: //0x80
- /*
- the shifting needs to be done on the 32bit unsigned long variable
- so that << 16 doesn't end up as zero.
- */
- getCmd();
- divider = cmdBytes[2];
- divider = divider << 8;
- divider += cmdBytes[1];
- divider = divider << 8;
- divider += cmdBytes[0];
- setupDelay();
- break;
- case SUMP_SET_READ_DELAY_COUNT://0x81:
- /*
- this just sets up how many samples there should be before
- and after the trigger fires. The readCount is total samples
- to return and delayCount number of samples after the trigger.
- this sets the buffer splits like 0/100, 25/75, 50/50
- for example if readCount == delayCount then we should
- return all samples starting from the trigger point.
- if delayCount < readCount we return (readCount - delayCount) of
- samples from before the trigger fired.
- */
- getCmd();
- readCount = 4 * (((cmdBytes[1] << 8) | cmdBytes[0]) + 1);
- if (readCount > MAX_CAPTURE_SIZE)
- readCount = MAX_CAPTURE_SIZE;
- delayCount = 4 * (((cmdBytes[3] << 8) | cmdBytes[2]) + 1);
- if (delayCount > MAX_CAPTURE_SIZE)
- delayCount = MAX_CAPTURE_SIZE;
- break;
- case SUMP_SET_FLAGS: //0x82
- /* read the rest of the command bytes and check if RLE is enabled. */
- getCmd();
- rleEnabled = ((cmdBytes[1] & B1000000) != 0);
- break;
- /* case '?': //debug dump vars
- Serial1.print("divider: 0x"); Serial1.println(divider, HEX);
- Serial1.print("trigger_values: 0x"); Serial1.println(trigger_values, BIN);
- Serial1.print("readCount: "); Serial1.println(readCount, DEC);
- Serial1.print("delayCount: "); Serial1.println(delayCount, DEC);
- Serial1.print("trigger: "); Serial1.println(trigger, DEC);
- Serial1.print("useMicro: "); Serial1.println(useMicro, DEC);
- Serial1.print("rleEnabled: "); Serial1.println(rleEnabled, DEC);
- Serial1.print("sample time us="); Serial1.println(tus, DEC);
- Serial1.print("delays ");Serial1.println(delays,DEC);
- Serial1.print("divider ");Serial1.println(divider,DEC);
- break;*/
- default:
- break;
- }
- }
- }
相应的配置文件: - # Configuration for SLLogicLogger
- # The short (single word) type of the device described in this profile
- device.type = SLLogicLogger
- # A longer description of the device
- device.description = SLLogicLogger (GD32F103RET6)
- # The device interface, SERIAL only
- device.interface = SERIAL
- # The device's native clockspeed, in Hertz.
- device.clockspeed = 120000000
- # Whether or not double-data-rate is supported by the device (also known as the "demux"-mode).
- device.supports_ddr = false
- # Supported sample rates in Hertz, separated by comma's
- device.samplerates = 22800000,10000000,3000000,1000000,300000,100000
- # The clockspeed used in the divider calculation, in Hertz. Defaults to 100MHz as most devices appear to use this.
- device.dividerClockspeed = 100000000
- # What capture clocks are supported
- device.captureclock = INTERNAL
- # The supported capture sizes, in bytes
- device.capturesizes = 61440
- # Whether or not the noise filter is supported
- device.feature.noisefilter = false
- # Whether or not Run-Length encoding is supported
- device.feature.rle = false
- # Whether or not a testing mode is supported
- device.feature.testmode = false
- # Whether or not triggers are supported
- device.feature.triggers = true
- # The number of trigger stages
- device.trigger.stages = 1
- # Whether or not "complex" triggers are supported
- device.trigger.complex = false
- # The total number of channels usable for capturing
- device.channel.count = 8
- # The number of channels groups, together with the channel count determines the channels per group
- device.channel.groups = 1
- # Whether the capture size is limited by the enabled channel groups
- device.capturesize.bound = false
- # Which numbering does the device support
- device.channel.numberingschemes = INSIDE, OUTSIDE
- # Is a delay after opening the port and device detection needed? (0 = no delay, >0 = delay in milliseconds)
- device.open.portdelay = 0
- # The receive timeout for the device (in milliseconds, 100 = default, <=0 = no timeout)
- device.receive.timeout = 100
- # Does the device need a high or low DTR-line to operate correctly? (high = true, low = false)
- device.open.portdtr = false
- # Which metadata keys correspond to this device profile? Value is a comma-separated list of (double quoted) names...
- device.metadata.keys = "SLLogicLogger"
- # In which order are samples sent back from the device? false = last sample first, true = first sample first
- device.samples.reverseOrder = true
- ###EOF###
全部文件: [ 此帖被huaweiwx在2016-06-19 16:45重新编辑 ]
|