From 77654ece88e9f58c774be5b9d921156eaeed00ce Mon Sep 17 00:00:00 2001 From: C-Glick <colton.glick@gmail.com> Date: Sun, 30 Jan 2022 20:29:07 -0600 Subject: [PATCH] Started work on DFU flashing, need to figure out how to send setup requests from host --- .../src/hal/src/usb.c | 19 +- .../tools/make/flash_dfu/cfusb.py | 201 ++++++++++++++++++ .../tools/make/flash_dfu/testdfu.py | 6 + 3 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/cfusb.py create mode 100644 crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/testdfu.py diff --git a/crazyflie_software/crazyflie-firmware-2021.06/src/hal/src/usb.c b/crazyflie_software/crazyflie-firmware-2021.06/src/hal/src/usb.c index ec2ee5e95..f129b089f 100644 --- a/crazyflie_software/crazyflie-firmware-2021.06/src/hal/src/usb.c +++ b/crazyflie_software/crazyflie-firmware-2021.06/src/hal/src/usb.c @@ -48,6 +48,8 @@ #include "crtp.h" #include "static_mem.h" +#include "debug.h" + NO_DMA_CCM_SAFE_ZERO_INIT __ALIGN_BEGIN USB_OTG_CORE_HANDLE USB_OTG_dev __ALIGN_END ; @@ -177,10 +179,23 @@ static uint8_t usbd_cf_Setup(void *pdev , USB_SETUP_REQ *req) USB_RX_TX_PACKET_SIZE); rxStopped = false; } - } else { + } else if(command == 0x02){ + //transition to DFU bootloader mode + + // arm-none-eabi-gcc 4.9.0 does not correctly inline this + // // // MSP function, so we write it out explicitly here. + __set_MSP(*((uint32_t*) 0x00000000)); + //__ASM volatile ("movs r3, #0\nldr r3, [r3, #0]\nMSR msp, r3\n" : : : "r3", "sp"); + + ((void (*)(void)) *((uint32_t*) 0x00000004))(); + + while (1); + } + + else { crtpSetLink(radiolinkGetLink()); } - + DEBUG_PRINT("USB setup request: %d, %d, %d, %d, %d ",req->bmRequest, req->bRequest, req->wValue, req->wIndex, req->wLength); return USBD_OK; } diff --git a/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/cfusb.py b/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/cfusb.py new file mode 100644 index 000000000..349c212cc --- /dev/null +++ b/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/cfusb.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# || ____ _ __ +# +------+ / __ )(_) /_______________ _____ ___ +# | 0xBC | / __ / / __/ ___/ ___/ __ `/_ / / _ \ +# +------+ / /_/ / / /_/ /__/ / / /_/ / / /_/ __/ +# || || /_____/_/\__/\___/_/ \__,_/ /___/\___/ +# +# Copyright (C) 2011-2013 Bitcraze AB +# +# Crazyflie Nano Quadcopter Client +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +""" +USB driver for the Crazyflie. +""" +import logging +import os + +import usb + +__author__ = 'Bitcraze AB' +__all__ = ['CfUsb'] + +logger = logging.getLogger(__name__) + +USB_VID = 0x0483 +USB_PID = 0x5740 + +try: + import usb.core + + pyusb_backend = None + if os.name == 'nt': + import usb.backend.libusb0 as libusb0 + + pyusb_backend = libusb0.get_backend() + pyusb1 = True + +except Exception: + pyusb1 = False + + +def _find_devices(): + """ + Returns a list of CrazyRadio devices currently connected to the computer + """ + ret = [] + + logger.info('Looking for devices....') + + if pyusb1: + for d in usb.core.find(idVendor=USB_VID, idProduct=USB_PID, find_all=1, + backend=pyusb_backend): + if d.manufacturer == 'Bitcraze AB': + ret.append(d) + else: + busses = usb.busses() + for bus in busses: + for device in bus.devices: + if device.idVendor == USB_VID: + if device.idProduct == USB_PID: + ret += [device, ] + + return ret + + +class CfUsb: + """ Used for communication with the Crazyradio USB dongle """ + + def __init__(self, device=None, devid=0): + """ Create object and scan for USB dongle if no device is supplied """ + self.dev = None + self.handle = None + self._last_write = 0 + self._last_read = 0 + + if device is None: + devices = _find_devices() + try: + self.dev = devices[devid] + except Exception: + self.dev = None + + if self.dev: + if (pyusb1 is True): + self.dev.set_configuration(1) + self.handle = self.dev + self.version = float( + '{0:x}.{1:x}'.format(self.dev.bcdDevice >> 8, + self.dev.bcdDevice & 0x0FF)) + else: + self.handle = self.dev.open() + self.handle.setConfiguration(1) + self.handle.claimInterface(0) + self.version = float(self.dev.deviceVersion) + + def get_serial(self): + # The signature for get_string has changed between versions to 1.0.0b1, + # 1.0.0b2 and 1.0.0. Try the old signature first, if that fails try + # the newer one. + try: + return usb.util.get_string(self.dev, 255, self.dev.iSerialNumber) + except (usb.core.USBError, ValueError): + return usb.util.get_string(self.dev, self.dev.iSerialNumber) + + def close(self): + if (pyusb1 is False): + if self.handle: + self.handle.releaseInterface() + else: + if self.dev: + usb.util.dispose_resources(self.dev) + + self.handle = None + self.dev = None + + def scan(self): + # TODO: Currently only supports one device + if self.dev: + return [('usb://0', '')] + return [] + + def set_crtp_to_usb(self, crtp_to_usb): + if crtp_to_usb: + _send_vendor_setup(self.handle, 0x01, 0x01, 1, ()) + else: + _send_vendor_setup(self.handle, 0x01, 0x01, 0, ()) + + def set_cf_to_dfu(self): + _send_vendor_setup(self.handle, 0x01, 0x01, 2, ()) + + + # Data transfers + def send_packet(self, dataOut): + """ Send a packet and receive the ack from the radio dongle + The ack contains information about the packet transmission + and a data payload if the ack packet contained any """ + try: + if (pyusb1 is False): + self.handle.bulkWrite(1, dataOut, 20) + else: + self.handle.write(endpoint=1, data=dataOut, timeout=20) + except usb.USBError: + pass + + def receive_packet(self): + dataIn = () + try: + if (pyusb1 is False): + dataIn = self.handle.bulkRead(0x81, 64, 20) + else: + dataIn = self.handle.read(0x81, 64, timeout=20) + except usb.USBError as e: + try: + if e.backend_error_code == -7 or e.backend_error_code == -116: + # Normal, the read was empty + pass + else: + raise IOError('Crazyflie disconnected') + except AttributeError: + # pyusb < 1.0 doesn't implement getting the underlying error + # number and it seems as if it's not possible to detect + # if the cable is disconnected. So this detection is not + # supported, but the "normal" case will work. + pass + + return dataIn + + +# Private utility functions +def _send_vendor_setup(handle, request, value, index, data): + if pyusb1: + handle.ctrl_transfer(usb.TYPE_VENDOR, request, wValue=value, + wIndex=index, timeout=1000, data_or_wLength=data) + else: + handle.controlMsg(usb.TYPE_VENDOR, request, data, value=value, + index=index, timeout=1000) + + +def _get_vendor_setup(handle, request, value, index, length): + if pyusb1: + return handle.ctrl_transfer(usb.TYPE_VENDOR | 0x80, request, + wValue=value, wIndex=index, timeout=1000, + data_or_wLength=length) + else: + return handle.controlMsg(usb.TYPE_VENDOR | 0x80, request, length, + value=value, index=index, timeout=1000) diff --git a/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/testdfu.py b/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/testdfu.py new file mode 100644 index 000000000..e000311dd --- /dev/null +++ b/crazyflie_software/crazyflie-firmware-2021.06/tools/make/flash_dfu/testdfu.py @@ -0,0 +1,6 @@ +from cfusb import CfUsb + +#TODO this devieid might need to be dynamic? +cfusb = CfUsb(devid=int(0)) + +cfusb.set_crtp_to_usb(True) \ No newline at end of file -- GitLab