I have an STM32F102 microcontroller and I want to program it via the Serial Port.
While there is a flasher available for windows, I want to do it on a Linux Machine. I tried doing it with this script
I have set BOOT0 = 1 and BOOT1 = 0, restarted the microcontroller. But it does not work. I get the following output
Can't init. Ensure BOOT0=1, BOOT1=0, and reset device
Traceback (most recent call last):
File "stm32loader.py", line 552, in <module>
bootversion = cmd.cmdGet()
File "stm32loader.py", line 140, in cmdGet
if self.cmdGeneric(0x00):
File "stm32loader.py", line 137, in cmdGeneric
return self._wait_for_ack(hex(cmd))
File "stm32loader.py", line 88, in _wait_for_ack
raise CmdException("No response to %s" % info)
__main__.CmdException: No response to 0x0
Here are a few tips:
Connect serial cable before resetting / powering up the board. Otherwise some transients can mess the serial bootloader up.
Make sure you are using a TTL level USB-to-serial converter instead of a RS-232 cable. RS-232 has inverted level, and worse still, its -15V to 15V voltage range can burn your STM32.
Make sure RX and TX are connected correctly.
Try using stm32flash instead.
Most STM32's serial bootloader does not support baud rate higher than 115200 as I remember. The bootloader can detect baud rate automatically, the one I usually use is 57600.
Some of these chips are being shipped with locked bootloaders. You will need to use STM32 Flash loader demonstrator to remove the protection. Windows only unfortunately but once it is unlocked you can use any machine.
Related
I'm having trouble loading code into my ESP8266 board. The error msg was posted below. Note that my board was working a year ago.
Arduino: 1.8.9 (Windows 10), Board: "Adafruit Feather HUZZAH ESP8266, 80 MHz, Flash, Disabled, All SSL ciphers (most compatible), 4M (1M SPIFFS), v2 Lower Memory, Disabled, None, Only Sketch, 115200"
Sketch uses 257696 bytes (24%) of program storage space. Maximum is 1044464 bytes.
Global variables use 26572 bytes (32%) of dynamic memory, leaving 55348 bytes for local variables. Maximum is 81920 bytes.
esptool.py v2.6
2.6
esptool.py v2.6
Serial port COM8
Connecting........_____....._____....._____....._____....._____....._____.....____Traceback (most recent call last):
File "C:\Users\Owen\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.5.2/tools/upload.py", line 25, in
esptool.main(fakeargs)
File
"C:/Users/Owen/AppData/Local/Arduino15/packages/esp8266/hardware/esp8266/2.5.2/tools/esptool\esptool.py", line 2653, in main
esp.connect(args.before)
File "C:/Users/Owen/AppData/Local/Arduino15/packages/esp8266/hardware/esp8266/2.5.2/tools/esptool\esptool.py", line 468, in connect
raise FatalError('Failed to connect to %s: %s' % (self.CHIP_NAME, last_error))
esptool.FatalError: Failed to connect to ESP8266: Timed out waiting for packet header
esptool.FatalError: Failed to connect to ESP8266: Timed out waiting for packet header
_
There could be many reasons for this problem.
1st proposal: the esp and the attached sensors etc. are consuming to much power. Detach the sensors and try to upload the sketch again. Or make sure, that you esp is getting enough power. (You could also try another micro-usb cable / power source)
2ns proposal: change the baudrate.
3rd proposal: If you connected an micro SD shield, detach the microSD card and try again.
These have been the cases, when I ran over this issue. I hope one of those guesses is going to help you.
I'm trying to send files over a half-duplex interface (RS-485) between a box PC running debian (4.19) and a SBC with an im6xDL.
Thanks to this community I can successfully transfer simple data between the units using picocom or by echoing/reading.
The box PC supports half-duplex RS-485 natively and has automatic RTS functions so that you can read/send data without any issue. The SBC on the other hand needs to be toggled to change into RX or TX mode.
This turned out to be a problem when I tried to send files from the box PC to the SBC.
On the box PC:
picocom /dev/ttyUSB0 -b 9600 -fn
C-a,C-S
***file: /home/user/test.txt
Transfer incomplete
*** exit status: 128
On the SBC
picocom /dev/ttymxc2 -b 9600 -fn -et
C-a,C-r
Terminal ready
�000000
As you can see something is terribly wrong, it is like it cannot interpret the bits when a file is being transferred.
My questions:
Is it possible to send files from the command line in half-duplex systems? (The SBC needs to be in RX mode the entire time).
Is there another way to achieve this that is more intuitive?
As always, thanks for the help and support :)
/W
See here:
Pymodbus - Read input register of Energy meter over rs485 on uart of raspberry pi3
The solution I presented there using pylibmodbus should work for any hardware with UART and one or two GPIO lines accessible from user space in Linux.
If, on the other hand, what you want to do is use something like picocom or minicom then you can take a look at the hardware-only solution using a 555 timer.
Of course, if prototyping circuits is not for you, you can always buy a USB to RS485 with half-duplex support. You have many available but those based on the MAX13487 IC seem to work very well.
EDIT: The solution using the 555 timer is not in the post I linked above but here together with some more background material on half-duplex RS485 links: RS485: Inappropriate ioctl for device
I have a device attached to a Raspberry Pi. The Pi is running ARCH Linux. The device communicates with the Pi via USB. The device has to be switched on and off via a pulse and I have control, from the Pi, of a relay which causes this pulse. However I can never be sure whether the device is initially on or off.
In my code I toggle the relay and then speculatively call open() on the device (with flags O_RDWR | O_NOCTTY). The problem is that if I am doing this when the device is off the open() call hangs. I have tried waiting for 1 second after the toggle, for things to settle, but that hasn't helped. I have tried calling stat() before the open() call but this always returns zero (so the device is there as far as stat() is concerned). I have tried specifying O_NON_BLOCK in the open() call but that causes it to always fail.
Can anyone suggest either (a) what I'm doing wrong or (b) a reliable way forward?
You can be certain that the device has powered if it has USB enumerated. You can use libudev to find the list of USB enumerated devices and check whether your device is on that list.
The command line "lsusb" does that. So if you need an example of how to use libudev then you can read the lsusb source code (https://github.com/gregkh/lsusb).
If you can be sure that the device will eventually turn up, the blocking open() ("hangs") may actually be what you want! The call to open() will return, hopefully with success, when your device turns up.
The stat() call simply checks if the device special file is there. It can't tell you if there is anything listening.
One possible way forward, would be to open() with O_NONBLOCK in an exponential back-off loop.
Depending on what you mean with "communicates via USB", you may want to use libusb. If it's just a USB serial port, wrapping open() yourself is probably the easiest though.
It's not clear what you have done to get a device file that survives disconnect.
The usual approach is to use hotplug+udev to create (and remove) the device symlinks, then the special file would only be there when the device is plugged in.
Courtesy of all the helpful people below, the quick answer was to include in my .rules file a "remove" action to go with the existing "add" action. So in the file where I have:
ACTION=="add", ATTRS{interface}=="Pololu Orangutan X2 Serial Adapter", MODE="7777", SYMLINK+="OrangutanUSB"
...to give me a /dev/OrangutanUSB device, I have included a new line:
ACTION=="remove", ATTRS{interface}=="Pololu Orangutan X2 Serial Adapter", MODE="7777", SYMLINK-="OrangutanUSB"
...to cause the operating system to remove the /dev/OrangutanUSB device when it has been powered off. This way the open() call fails correctly when the device has gone, rather than hanging.
Ultimately, what I should do is check that the device is enumerated, rather than expecting open() to fail, but that can wait until I have the time. For now my code works as originally intended.
I need to run my /dev/ttyUSB0 (prolific pl2303 USB-RS232 converter) at 250kbps using c. Everywhere I looked everyone said that the nearest achievable speed is 230400 bps (http://lxr.linux.no/#linux+v3.9.5/drivers/usb/serial/pl2303.c and a few lines later (line 325) "NOTE: Only the values defined in baud_sup are supported !").
But I'm 100% sure that it can be done, because on windows (using c# default SerialPort component) I can just set 250000 as the baudrate, and it wil happily put out data at that speed (measured with an oscilloscope, so it's not switching to the nearest available or to 9600 as described in the linux driver at line 325!).
Does anyone know a way to set tat custom baudrate in linux?
And before you ask, I have developed a device that communicates at 250kbps, that speed is needed and is the highest I can get without errors, so no I can't change it.
It's a problem in the linux driver. From line 333 to line 348, the driver forces a baudrate. Removing that code, the baudrate gets calculated with the formula 12 * 1000 * 1000 * 32 / baud, and that gives an error of 0% at 250kbps, perfectly in line with what I get on windows. I'm looking forward to improve the official driver.
Posix requires changing RTS pin on port opening. I want a way to avoid it.
I have no idea why you'd want to do this, but this can be done pretty easily by modifying the linux kernel driver for your serial console so it doesn't toggle RTS. For example, for the 8250-series driver in drivers/tty/serial/8250/ you could change every write to the MCR register (UART_MCR) to ensure that bit 1 (mask is UART_MCR_RTS) is never set.
Since it's abstracted away in userspace, you're out of luck if you want to do this without modifying the kernel driver.
Having the same problem, I'd give it a try by patching the ftdi_sio kernel driver. You just need to uncomment a small piece of code in ftdi_dtr_rts() like this:
static void ftdi_dtr_rts(struct usb_serial_port *port, int on) {
...
/* drop RTS and DTR */
if (on)
set_mctrl(port, TIOCM_DTR /*| TIOCM_RTS*/); // <<-- HERE
else
clear_mctrl(port, TIOCM_DTR /*| TIOCM_RTS*/); // <<-- and HERE
}
and the RTS handshake line is not longer changed upon open() call.
Note, that the uart than might not longer working with RTS/CTS hardware handshake, as long as your modified kernel driver is loaded. But you can still control the state of the RTS handshake line manually by calling e.g.:
int opins = TIOCM_RTS;
ioctl(tty_fd, TIOCMBIC, &opins);
I'd tested this with the Ctrl+A+G command of picocom 2.3a, running Kubuntu 16.04 64 bit and Ftdi FT2232H based usb uart adapter.
You might find more details on this topic here.
A change in the DTR pin can be (eventually) avoided using the command line
stty -F /dev/ttyUSB0 -hupcl
This has the effect of making DTR turn on; and subsequently when the port is opened and closed, DTR is not affected.
Source: https://raspberrypi.stackexchange.com/questions/9695/disable-dtr-on-ttyusb0/27706#27706
And there is code there to do the same thing from python via termios, this can be done before opening the port via pyserial:
import termios
path = '/dev/ttyACM0'
# Disable reset after hangup
with open(path) as f:
attrs = termios.tcgetattr(f)
attrs[2] = attrs[2] & ~termios.HUPCL
termios.tcsetattr(f, termios.TCSAFLUSH, attrs)
The OP was running this on a Raspberry Pi, but I just tried it on Linux Mint on x86_64, it worked. I don't know how RTS is affected.
The reason I find this useful, is for communication with an Arduino Nano - which has a USB-> serial chip on board - and normally the Arduino gets reset every time you open the serial port from linux (rising edge of DTR causes reset). For some applications, this is not a problem, but it's clearly useful to avoid this for other applications, and it's not so easy to remove that tiny capacitor from the Arduino which connects DTR to reset.
You will still get a single reset when the stty command is executed (after plugging in the USB cable). But at least you can then keep opening and closing the serial port after that without further resets.
calling fopen("/dev/ACM0", "r") doesn't require you do do anything:) You may not receive the data you expect though.