STM32F103 programming USB_DP, USB_DM, SWDIO, SWCLK ? - Page 1
Forum section: electronics / general

author: hydrogen18
author_rank: Contributor
timestamp: March 06, 2022, 09:46:56 pm
content: Hi all,Let me preface this by saying I know very little about the STM32F103 part, at all.I bought this simple board off Ali Express for almost nothing that consists of a STM32F103, an AD9850, a 125 MHz clock, and some op amps.The USB port on the device doesn't seem to do anything (no device detected when plugged in) despite beiong connected to PA12/PA11 on the chipIt works but the frequency shown on the screen is only sometimes the frequency actually output. The AD9850 always make a nice sine wave, so my conclusion is the microcontroller isn't sending it the right bits for the tuning word.The AliExpress seller sent me the source code (or pretty close, looks like they use the same thing for AD9851 boards with minor tweaks). It's full of obvious errors, including that it doesn't try and guarantee the clock is held high for the 3.5ns time the AD9850 needs to load from the parallel interface. So it makes sense that the board would "work" but never quite get the frequency output correct. Some bits get loaded wrong, if they are high enough in the tuning word the freq is way, way off.The source code is a uVision project, which is apparently a commercial product only for windows.So rather than bothering to deal with unusual commercial software I want to do two things.1. Pull the complete ROM off the board as a backup, so I can always go back to it2. Reprogram the device via the Arduino IDE. I can just write my own software in less time than trying to understand a commercial product like uVision.The USB header does not identify as a device on any PC I have tried. I'm assuming something may not be setup right in the chip?There is another header labeled "3.3v, SDI, SCL, GND" on the board I can populate. That gets connected to SWDIO & SWCLK. From what I can tell on a STM32F103 "blue pill" this is called J-Link. Can I do reprogramming via this header or should I just give up on this board? It was only $28 after all.

author: hydrogen18
author_rank: Contributor
timestamp: March 07, 2022, 05:01:31 pm
content: One observation I made: I have some stm32 "blue pill" dev boards laying around. Those don't identify as a USB device when plugged in either. Maybe STM32 boards require some pin to be pulled low (or high) in order to act like a USB device?

author: langwadt
author_rank: Super Contributor
timestamp: March 07, 2022, 05:28:24 pm
content: https://www.electrosoftcloud.com/en/stm32f103-bootloader-and-programming/

author: thm_w
author_rank: Super Contributor
timestamp: March 07, 2022, 11:27:49 pm
content: Quote from: hydrogen18 on March 06, 2022, 09:46:56 pmIf that goes to PA13 (pin 34) and PA14 (pin 37), which you seem to be saying, then yeah you can reprogram via the header.You may or may not be able to download their code, depending on if they locked the firmware. But you can always erase and reprogram.Its called SW-DP serial wire debug port.j-link is one programmer you can use, you can also get a clone stlink, or real stlink for not much money ($3-15).uVision you might be able to get a 30 day trial:https://www.keil.com/demo/eval/armv4.htmCan you upload the code they sent you here?

author: hydrogen18
author_rank: Contributor
timestamp: March 08, 2022, 02:31:28 pm
content: This is the complete ZIP I was sent. The actual C source code is in what I think is extended ASCII. It doesn't seem to UTF-8. The comments all use character codes that are invalid, but must be valid in some sort of extended ASCII that displays Chinese glyphs. I can't read chinese anyways, so I ignored.The XML files reference uVision, so presumably I would need that to recompile this.The actual bug is simple. The code bit bangs the parallel IO to the AD9850, which is fine. The STM32 is running at 72 Mhz. This is the routine after I formatted it to be readable:Code:void ad9851_wr_parallel(u8 w0, double freq){volatile u32 w;long int y;double x;volatile u32 w_test;x=4294967295 / 180;freq=freq / 1000000; // Convert to MHzfreq=freq*x;y = (long int)freq;w=w0;//AD9851_DataBus=w|(w^0xff)<<16; //w0w_test = (w&0X000000FF);AD9851_DataBus = (AD9851_DataBus & 0XFF00)|(w_test);ad9851_w_clk=1;ad9851_w_clk=0;w=(y>>24);//AD9851_DataBus=w|(w^0xff)<<16; //w0//w_test = w|(w^0xff)<<16;w_test = (w&0X000000FF);AD9851_DataBus = (AD9851_DataBus & 0XFF00)|(w_test);ad9851_w_clk=1;ad9851_w_clk=0;w=(y>>16);//AD9851_DataBus=w|(w^0xff)<<16; //w0//w_test = w|(w^0xff)<<16;w_test = (w&0X000000FF);AD9851_DataBus = (AD9851_DataBus & 0XFF00)|(w_test);ad9851_w_clk=1;ad9851_w_clk=0;w=(y>>8);//AD9851_DataBus=w|(w^0xff)<<16; //w0//w_test = w|(w^0xff)<<16;w_test = (w&0X000000FF);AD9851_DataBus = (AD9851_DataBus & 0XFF00)|(w_test);ad9851_w_clk=1;ad9851_w_clk=0;w=(y>>=0);//AD9851_DataBus=w|(w^0xff)<<16; //w0w_test = (w&0X000000FF);AD9851_DataBus = (AD9851_DataBus & 0XFF00)|(w_test);ad9851_w_clk=1;ad9851_w_clk=0;ad9851_fq_up=1;ad9851_fq_up=0;}There is so many odd points here:1. The first argument w0 is always 0.2. The value "180" should be "125" for AD9850, I think I got sent the AD9851 code. Which is going to be near identical3. volatile local variables? See below3. The clock isn't created correctlyFor exampleCode:#define ad9851_w_clk PBout(1)ad9851_w_clk=1;ad9851_w_clk=0;I've never seen a microcontroller where this guarantees the pin is high for 1 cycle. If you're running a really slow microcontrollerat 4 MHz or whatever, it's probably fine. But this STM32 is running at 72Mhz.I would always write this asCode:ad9851_w_clk=1;NOP(); // Whatever macro you need in your IDE to get a no-opad9851_w_clk=0;Just to make sure the pin sits there high for 1 cycle. They probably added "volatile" thinking it "fixed" things because it made the compiler turn off lots of optimizations, which made the code slower.This makes lots of sense, because my frequency counter is almost always close to the value that the is displayed on the LCD. But never quite right. So usually some of the low bits in the tuning word get flipped. Sometimes a high bit gets flipped and it is way off, as in double the desired frequency.so my options are1. Download the code, hand edit the assembly to add the NOPs2. Just write my own code to replace everything. This isn't a very complex device.

author: ozcar
author_rank: Frequent Contributor
timestamp: March 08, 2022, 07:09:17 pm
content: Quote from: hydrogen18 on March 08, 2022, 02:31:28 pmDo you know for sure that it is running at 72MHz? Depending on how the clock is set up, it might not be.Do you have some way to see what the clock pulse looks like?

author: westfw
author_rank: Super Contributor
timestamp: March 08, 2022, 11:08:09 pm
content: QuoteReally? How can it not be, for some definition of "cycle" and "high"? (at high frequencies, your theoretically square pulse may become a rather messy-looking rounded triangle, but it IS trying...)On an STM32F103, it's likely to be more than a single cycle, give the lack of single-cycle IO bus and an instruction set that is probably using a sequence of read, modify, and write instructions to achieve single-bit writes. (Could be using bit-banding, but AFAIK, bit-banding never made it into most actual application libraries. You didn't show what PBout(1) means.)On the other hand, your suggested fix of adding a NOP may not work on ARM, because NOP is defined to not necessarily require any cycles to "execute."Whether the pulse produced is "long enough" is a separate question. ad9851 says 3.5ns..(When in doubt, measure it...)

author: thm_w
author_rank: Super Contributor
timestamp: March 09, 2022, 12:14:00 am
content: There is now a free version of Keil, in addition to the 30 day trial I mentioned above, so I would try to compile it with one of those:https://www.keil.com/pr/article/1299.htmSince there is no USB code that I see in that .zip file, and STM32F103 does not contain a USB bootloader, the USB port will not do anything.

author: ozcar
author_rank: Frequent Contributor
timestamp: March 09, 2022, 01:56:25 am
content: Quote from: westfw on March 08, 2022, 11:08:09 pmIn the interest of science, I grabbed a blue pill board and tried this:Code:while ( 1 ){GPIOB->BSRR = GPIO_BSRR_BS1;GPIOB->BSRR = GPIO_BSRR_BR1;GPIOB->BSRR = GPIO_BSRR_BS1;GPIOB->BSRR = GPIO_BSRR_BR1;GPIOB->BSRR = GPIO_BSRR_BS1;GPIOB->BSRR = GPIO_BSRR_BR1;GPIOB->BSRR = GPIO_BSRR_BS1;GPIOB->BSRR = GPIO_BSRR_BR1;... more of the same ...}That resulted in this:Code:0x0800507c: 0a 4bldrr3, [pc, #40]; (0x80050a8 <loop()+44>) GPIOB address0x0800507e: 02 21movsr1, #20x08005080: 19 61strr1, [r3, #16]0x08005082: 4f f4 00 32mov.wr2, #131072; 0x200000x08005086: 1a 61strr2, [r3, #16]0x08005088: 19 61strr1, [r3, #16]0x0800508a: 1a 61strr2, [r3, #16]0x0800508c: 19 61strr1, [r3, #16]0x0800508e: 1a 61strr2, [r3, #16]So, the first high pulse created by that was longer than the rest. The subsequent highs (and lows) were around 28ns = 2 cycles at 72MHz.Whatever that PBout(1) does, it is hard to see how if could be any faster, and no way that the pulse would be too short.

author: thm_w
author_rank: Super Contributor
timestamp: March 09, 2022, 02:08:09 am
content: Code:#define PBout(n) BIT_ADDR(GPIOB_ODR_Addr,n) //输出#define PBin(n) BIT_ADDR(GPIOB_IDR_Addr,n) //输入#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))#define MEM_ADDR(addr) *((volatile unsigned long *)(addr))#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))

author: hydrogen18
author_rank: Contributor
timestamp: March 09, 2022, 03:43:52 am
content: Quote from: ozcar on March 09, 2022, 01:56:25 amHmm, thanks for the test. I guess my theory was wrong then, 28ns should be long enough. Maybe I'll spend some more time reviewing the code.

author: ozcar
author_rank: Frequent Contributor
timestamp: March 09, 2022, 03:45:35 am
content: Quote from: thm_w on March 09, 2022, 02:08:09 amHaving gotten so far, I tried that instead (had to add definition for GPIOB_ODR_Addr):Code:while ( 1 ){ad9851_w_clk=1;ad9851_w_clk=0;ad9851_w_clk=1;ad9851_w_clk=0;ad9851_w_clk=1;ad9851_w_clk=0;ad9851_w_clk=1;ad9851_w_clk=0;...}Resulting code looks very similar to what I had before:Code:0x0800507c: 05 4bldrr3, [pc, #20]; (0x8005094 <loop()+24>) bitband addr of GPIOB ODR0x0800507e: 01 21movsr1, #10x08005080: 19 60strr1, [r3, #0]0x08005082: 00 22movsr2, #00x08005084: 1a 60strr2, [r3, #0]0x08005086: 19 60strr1, [r3, #0]0x08005088: 1a 60strr2, [r3, #0]0x0800508a: 19 60strr1, [r3, #0]0x0800508c: 1a 60strr2, [r3, #0]0x0800508e: 19 60strr1, [r3, #0]0x08005090: 1a 60strr2, [r3, #0]However the resulting pulses are longer - the ones other than the first seem to be 6 cycles compared to the 2 cycles I had before.Edit: Actually, I just noticed that now the first pulse is not longer than the rest of them.

author: hydrogen18
author_rank: Contributor
timestamp: March 09, 2022, 02:10:03 pm
content: Thanks again. I really appreciate the time you've spent on this as it saves me a bunch of effort on my part and indicates my original course of work was heading the wrong way.Last time I put my scope probe on the clock pin, it seemed to pull it low the entire time. It's really hard to probe, I'm not setup for working on something on a PCB honestly. I'm usually not actually troubleshooting something built on a PCB.I got an ST-Link v2 in the mail yesterday and I will attempt to download the firmware next. From there I'll see if I can just upload a simple program that sweeps between two frequencies.I'm relatively certain the problem is flipped bits in the AD9850 tuning word. It just seems my theory was wrong. One possibility is that since the item came from AliExpress, the AD9850 may actually be from a rejected or bad batch. I have no idea what the yields are like on a DAC, but I would assume some fail some sort of factory test and are normally destroyed.The other thing I thought about is I do not know how a "double" is implemented on this STM32. That is how they calculate the tuning word. Is it an actual hardware floating point number or something done in software?

author: thm_w
author_rank: Super Contributor
timestamp: March 09, 2022, 11:25:01 pm
content: Double is floating point yes, 8 bytes.On the F103 its calculated in software, no hardware floating point unit for doubles.There are some threads about cheap AD9850'shttps://www.eevblog.com/forum/projects/too-good-to-be-true-fake-ad9850/https://www.eevblog.com/forum/projects/chinese-ad9850-dds-modules-questions/Most likely they are real and working, but, no guarantee of course. We will see once you write the test software.

author: westfw
author_rank: Super Contributor
timestamp: March 10, 2022, 12:33:26 am
content: QuoteAh hah! Someone DID end up with bit-banding in actual "production" software! Neat. But I don't think I particularly care for the syntax they ended up using, since it doesn't seem very portable to a chip without the bitbanding support.QuoteThank you for doing the actual experiment (for both cases!)I guess it makes sense that the bitband example is slower (3x!), since it presumably has to convince its bus hardware to do a full R/M/W cycle. But no wonder bitbanding didn't catch on!

author: hydrogen18
author_rank: Contributor
timestamp: March 10, 2022, 10:36:15 pm
content: I got the ST Link v2 connected to the device.Using st-info shows thisCode:Found 1 stlink programmersversion: V2J29S7serial: 30005400110000475130514Eflash: 47382528 (pagesize: 1024)sram: 20480chipid: 0x410dev-type: STM32F1xx_MDFailed to parse flash type or unrecognized flash typedetected chip_id parametres# Device Type: STM32F1xx_MD# Reference Manual: RM0008#chip_id 0x410flash_type 1flash_size_reg 0x1ffff7e0flash_pagesize 0x400sram_size 0x5000bootrom_base 0x1ffff000bootrom_size 0x800option_base 0x1ffff800option_size 0x10flags 2Found 1 stlink programmersversion: V2J29S7serial: 30005400110000475130514Eflash: 0 (pagesize: 1024)sram: 20480chipid: 0x410detected chip_id parametres# Device Type: STM32F1xx_MD# Reference Manual: RM0008#chip_id 0x410flash_type 1flash_size_reg 0x1ffff7e0flash_pagesize 0x400sram_size 0x5000bootrom_base 0x1ffff000bootrom_size 0x800option_base 0x1ffff800option_size 0x10flags 2dev-type: STM32F1xx_MDSo I guess the device can't be identified? I think the device is a STM32F103C8. Flash should be 0x08000000 to 0x0801fffTrying to dumping it outputs thisCode:LD_LIBRARY_PATH=/usr/local/lib st-flash read firmware.bin 0x08000000 0x1ffffst-flash 1.7.0-186-gc4762e6Failed to parse flash type or unrecognized flash typedetected chip_id parametres# Device Type: STM32F1xx_MD# Reference Manual: RM0008#chip_id 0x410flash_type 1flash_size_reg 0x1ffff7e0flash_pagesize 0x400sram_size 0x5000bootrom_base 0x1ffff000bootrom_size 0x800option_base 0x1ffff800option_size 0x10flags 22022-03-10T17:34:58 INFO common.c: STM32F1xx_MD: 20 KiB SRAM, 896 KiB flash in at least 1 KiB pages.2022-03-10T17:34:58 INFO common.c: read from address 0x08000000 size 131071But the file "firmware.bin" is mostly zeros or the pattern "80 00 00 00 03 00 03 01". Anyone aware of what is going on here?

author: thm_w
author_rank: Super Contributor
timestamp: March 10, 2022, 11:08:48 pm
content: Chip_id 0x410 means its STM32F101, 102, or 103.https://github.com/stlink-org/stlink/blob/develop/doc/devices_boards.mdA lot of the dies are shared, so you often can't tell what specific part number it actually is.How much is "mostly zero"? You'd have to compile their program to see how much space it actually takes, maybe its not that much.If you run the stlink program, you can go to Target -> Option Bytes window. They released a newer version STM32CubeProgrammer, I'm not sure how that one works.

author: hydrogen18
author_rank: Contributor
timestamp: March 11, 2022, 02:06:48 am
content: using the STM32CubeProgrammer application and trying to read data from 0x08000000 gives me a popup showing this errorCode:Error: data read failed

author: ozcar
author_rank: Frequent Contributor
timestamp: March 11, 2022, 08:27:37 pm
content: Quote from: thm_w on March 10, 2022, 11:08:48 pmI did not try to figure out how the various things in the zip file that was posted hang together. There is only one hex file there though, the somewhat strangely named VirtualCOMPort.hex, which has size 0x7400 (29k bytes). There is a text string in that "DDS-9850" so maybe that is it.I've never tried to read a device that has been programmed to prevent reading, so I don't know how that shows up. I also don't know why they would have tried to prevent reading the flash, but still make the source code available.

author: thm_w
author_rank: Super Contributor
timestamp: March 11, 2022, 10:38:20 pm
content: Did you try to read the option bytes though?For STM32F1 the location is 0x06000000https://wiki.segger.com/STM32F1The hex file ozcar posted does not appear to be protected, but I guess they could manually protect it after the fact. I would assume thats the right file.

author: hydrogen18
author_rank: Contributor
timestamp: March 12, 2022, 01:17:36 am
content: I thought the option bytes would be at 0x1ffff000 based off the datasheet. Reading that gives me 0 bytes unfortunatelyCode:LD_LIBRARY_PATH=/usr/local/lib st-flash read option_bytes.bin 0x1ffff000 0x800st-flash 1.7.0-186-gc4762e6Failed to parse flash type or unrecognized flash typedetected chip_id parametres# Device Type: STM32F1xx_MD# Reference Manual: RM0008#chip_id 0x410flash_type 1flash_size_reg 0x1ffff7e0flash_pagesize 0x400sram_size 0x5000bootrom_base 0x1ffff000bootrom_size 0x800option_base 0x1ffff800option_size 0x10flags 22022-03-11T20:15:31 INFO common.c: STM32F1xx_MD: 20 KiB SRAM, 0 KiB flash in at least 1 KiB pages.2022-03-11T20:15:31 INFO common.c: read from address 0x1ffff000 size 2048ericu@jagdtiger:~$ ls -l option_bytes.bin-rwx------ 1 ericu ericu 0 Mar 11 20:15 option_bytes.binThe other address doesn't seem to work eitherCode:$ LD_LIBRARY_PATH=/usr/local/lib st-flash read option_bytes.bin 0x06000000 0x800st-flash 1.7.0-186-gc4762e6Failed to parse flash type or unrecognized flash typedetected chip_id parametres# Device Type: STM32F1xx_MD# Reference Manual: RM0008#chip_id 0x410flash_type 1flash_size_reg 0x1ffff7e0flash_pagesize 0x400sram_size 0x5000bootrom_base 0x1ffff000bootrom_size 0x800option_base 0x1ffff800option_size 0x10flags 22022-03-11T20:17:11 INFO common.c: STM32F1xx_MD: 20 KiB SRAM, 0 KiB flash in at least 1 KiB pages.2022-03-11T20:17:11 INFO common.c: read from address 0x06000000 size 2048ericu@jagdtiger:~$ ls -l option_bytes.bin-rwx------ 1 ericu ericu 0 Mar 11 20:17 option_bytes.bin

author: hydrogen18
author_rank: Contributor
timestamp: March 12, 2022, 01:22:42 am
content: I wanted to make sure my software and STLink device was working so I plugged in my STM32 blue pill device to it and just issued the same command. Seems to work fine:Code:LD_LIBRARY_PATH=/usr/local/lib st-flash read option_bytes.bin 0x1ffff000 0x800st-flash 1.7.0-186-gc4762e6Failed to parse flash type or unrecognized flash typedetected chip_id parametres# Device Type: STM32F1xx_MD# Reference Manual: RM0008#chip_id 0x410flash_type 1flash_size_reg 0x1ffff7e0flash_pagesize 0x400sram_size 0x5000bootrom_base 0x1ffff000bootrom_size 0x800option_base 0x1ffff800option_size 0x10flags 22022-03-11T20:21:17 INFO common.c: STM32F1xx_MD: 20 KiB SRAM, 64 KiB flash in at least 1 KiB pages.2022-03-11T20:21:17 INFO common.c: read from address 0x1ffff000 size 2048ericu@jagdtiger:~$ ls -l option_bytes.bin-rwx------ 1 ericu ericu 2048 Mar 11 20:21 option_bytes.binericu@jagdtiger:~$ hd option_bytes.bin00000000 fc 01 00 20 21 f0 ff 1f 65 f7 ff 1f 67 f7 ff 1f |... !...e...g...|00000010 df f8 04 d0 00 f0 aa fb fc 01 00 20 00 47 00 00 |........... .G..|00000020 00 48 00 47 11 f0 ff 1f ff 49 a1 f8 04 08 b1 f8 |.H.G.....I......|00000030 00 08 40 06 fb d5 70 47 fd 49 fc 48 08 60 70 47 |..@...pG.I.H.`pG|00000040 fc 48 c1 68 c9 07 fc d1 70 47 fa 48 fa 49 81 60 |.H.h....pG.H.I.`|00000050 fa 49 81 60 70 47 f7 48 f7 49 41 60 f7 49 41 60 |.I.`pG.H.IA`.IA`|So I wonder if the STM32 had something weird done to it so that J-Link can't be used at all?It seems to show that Boot0 Is pulled low via 210K resistor and Boot1 is not connected (so high). So If I understand correctly that boots from user flash?

author: DavidAlfa
author_rank: Super Contributor
timestamp: March 12, 2022, 07:21:10 am
content: Quote from: hydrogen18 on March 12, 2022, 01:22:42 amCorrect.Using command line tools is so messy and time-wasting, why don't you use ST-Link utility?

author: darkspr1te
author_rank: Frequent Contributor
timestamp: March 12, 2022, 08:44:51 am
content: Quote from: hydrogen18 on March 08, 2022, 02:31:28 pmI was bored so i ported this app to platformio,I have not debugged anything,I have modded some files in order to build correctly (lcd_clear, include <cstring>)I have added defines which where not present in original source code nor on the net in some header file, defines could be waaay wrong.( -DK_NO=1 etc for timer.c )I have not tested this on a board as i dont have the AD etc so little pointplatformio.ini has not been configered for stlink but adding it is as easy as addingupload_protocol = stlinkto platformio.ini under framework=cmsisto switch between old lcd and new lcd driver change+<HARDWARE/LCD/*>to+<HARDWARE/LCD_OLD/*>and-IHARDWARE/LCD/to-IHARDWARE/LCD_OLD/This was just a exercise to see how quickly i could port a Keil CMSIS project to platformio build IDE , time taken is around 2 hours.darkspr1te