Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for optional SD Card programming #131

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
142 changes: 123 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ make
The menuconfig will present the following options:
- `Microcontroller Architecture`: Choose between lpc176x, stm32 and rp2040
- `Processor model`: Options depend on the chosen architecture
- `SD Card Configuration`: See the [SD Card Configuration](#sd-card-configuration)
section below.
- `Build Katapult deployment application`: See the [deployer](#katapult-deployer)
section below
section below.
- `Disable SWD at startup`: This is an option for GigaDevice STM32F103
clones. Note that this is untested for the bootloader, GigaDevice clones
may not work as expected.
Expand All @@ -51,8 +53,10 @@ The menuconfig will present the following options:
enabled it is possible to enter the bootloader by pressing the reset button
twice within a 500ms window.
- `Enable bootloader entry on button (or gpio) state`: Enable to use a gpio
to enter the booloader.
- `Button GPIO Pin`: The Pin Name of te
to enter the bootloader.
- `Button GPIO Pin`: The Pin Name of the GPIO to use as a button. A hardware
pull-up can be enabled by prefixing a `^`, and a pull-down can be enabled by
prefixing a `~`.
- `Enable Status Led`: Enables the option to select a status LED gpio.
- `Status LED GPIO Pin`: The pin name for your LED. The Pin can be inverted
if the LED is on when the pin is low. For example, the status LED Pin for a
Expand Down Expand Up @@ -80,19 +84,23 @@ with Katapult again.
1) Make sure the `klipper` service stopped.
2) Build Klipper with CAN support and with the a bootloader offset matching that
of the "application offset" in Katapult.
3) Enter the bootloader. This will occur automatically if no program is detected.
If you built Katapult with an alternative method of entry you may use that.
If upgrading from a currently flashed version of Klipper the `flashtool.py`
script will command the device to enter the bootloader (currently for CAN
devices only).
3) Enter the bootloader. Katapult automatically enters the bootloader if it
detects that the application area of flash is empty. When upgrading from a
currently flashed version of Klipper the `flashtool.py` script will command
USB and CANBus devices to enter the bootloader. Note that "USB to CAN
bridge devices" and "UART" devices cannot be auto-detected. If the device
is not in bootloader mode it is necessary to first manually request the
bootloader with the `-r` option, then rerun the script without `-r` to
perform the upload. Devices running software other than Klipper will need
to request the bootloader with their own method.
3) Run the flash script:
For CAN Devices:
```
cd ~/katapult/scripts
python3 flashtool.py -i can0 -f ~/klipper/out/klipper.bin -u <uuid>
```
Replace <uuid> with the appropriate uuid for your can device. If
the device has not been previouisly flashed with Klipper, it is possible
the device has not been previously flashed with Klipper, it is possible
to query the bootloader for the UUID:

```
Expand All @@ -105,10 +113,12 @@ with Katapult again.
"bus off" it becomes unresponsive. The node must be reset to recover.**

For USB/UART devices:
Before flashing, make sure pyserial is installed. This step only needs to
be performed once:
Before flashing, make sure pyserial is installed. The command required
for installation depends on the the linux distribution. Debian and Ubuntu
based distros can run the following commands:
```
pip3 install pyserial
sudo apt update
sudo apt install python3-serial
```
```
python3 flashtool.py -d <serial device> -b <baud_rate>
Expand Down Expand Up @@ -139,10 +149,11 @@ options:
Path to Klipper firmware file
-u <uuid>, --uuid <uuid>
Can device uuid
-q, --query Query Bootloader Device IDs
-q, --query Query Bootloader Device IDs (CANBus only)
-v, --verbose Enable verbose responses
-r, --request-bootloader
Requests the bootloader and exits (CAN only)
Requests the bootloader and exits
-s, --status Connect to bootloader and print status
```

### Can Programming
Expand All @@ -157,17 +168,110 @@ The `-f` option defaults to `~/klipper/out/klipper.bin` when omitted.

The `-d` option is required. The `-b` option defaults to `250000` if omitted.

### Request Bootloader (CAN Devices Only)
If `flashtool` detects that the device is connected via USB, it will check
the USB IDs to determine if its currently running Klipper. If so, the
`flashtool` will attempt to request the bootloader, waiting until it detects
Katapult.

When the `-r` option is supplied in addition to `-u` (and optionally `-i`)
the script will request that the node enter the bootloader. The script will
then immediately exit, no attempt will be made to upload a new binary over the
canbus. This is particularly useful for Klipper devices running "USB to CAN
### Request Bootloader and Exit

When the `-r` option is supplied `flashtool` request that the MCU enter
the bootloader. Flashtool will then immediately exit, no attempt will be
made to upload a new binary over the canbus.

This is particularly useful for Klipper devices configured in "USB to CAN
bridge mode". These devices upload firmware using DFU and/or Katapult-USB. This
option allows the user to enter the bootloader without physical access to the
board, then use the appropriate tool (`dfu-util` or `flashtool.py -d`) to
upload the new binary.

Additionally, the `-r` option can be used with devices connected to the host
over a UART connection to request Klipper's bootloader.

## SD Card Programming

Katapult offers optional SD Card support. When configured, an SD Card
may be used to upload firmware in addition to the primary interface
(CANBus, USB, or UART). This is useful for bench updates or as a
fallback when it isn't possible to flash using the primary interface.

Unlike most stock bootloaders, Katapult does not initialize the SD Card
and check for a new firmware file on every restart. The user must explicitly
enter the bootloader to initiate an SD Card upload. It is recommended to
either configure the "double reset" or a GPIO Button when enabling SD Card
programming so bootloader entry is possible without using `flashtool.py`.

Upon entering the bootloader, Katapult will look for a new `firmware file`,
and if detected it will begin writing. If a `status led` is configured it
will blink rapidly during the programming procedure. After successful completion
Katapult will rename the firmware file's extension to `.cur`, reset the MCU,
and jump to the application. If Katapult encounters an error during programming
it will attempt to rename the firmware file with a `.err` extension, then drop
to command mode.

If the `firmware file` does not exist or if there is an error initializing the
SD Card, Katapult will enter command mode. In this mode the `status led`
will blink slowly, and Katapult is read to accept commands over the primary
interface, such as those issued by `flashtool.py`.

Katapult supports SPI and Software SPI SD Card interfaces for all supported
micro-controllers. SDIO is available for STM32F4 series MCUs.

### SD Card Configuration

The following Options are available in the `SD Card Configuration` menu:
- `SD Card Interface`: The interface used to communicate with the SD Card.
Choices are `disabled`, hardware SPI modes, Software SPI, and SDIO modes.
- `SD Card Software SPI Pins`: Only available when `Software SPI` is selected
as the `SD Card Interface`. Must be three comma separated pins; MISO, MOSI,
and SCLK.
- `SD Card SPI CS Pin`: The Chip Select pin when one of the SPI modes (including
Software SPI) is selected.
- `Firmware file name`: The name of the firmware file that will trigger an upload.
Defaults to `firmware.bin`. **NOTE:** Avoid using a `.cur` or `.err` extensions
when customizing the file name. Doing so will result in Katapult deleting the
firmware file after an upload rather than renaming it.
- `Enable Long File Name Support`: When enabled, the firmware file name supports
FAT long file names. This allows the `Firmware file name` to have a base name
longer than 8 characters and extensions longer than 3 characters. This option
increases the size of the binary by roughly 2.5 KiB.

For most configurations the total size of Katapult's binary should be under 16KiB
when SD Card support is configured, thus a 16 KB `Application start offset` should be sufficient. One exception to this is the `RP2040` when the primary interface
is `CANBus` and `Long File Name Support` is enabled. This will result in a binary
larger than 16 KiB. It should be noted that `Klipper` currently only supports a
16 KiB bootloader offset for the `RP2040`.

### Troubleshooting

As mentioned above, Katapult will enter command mode if it encounters an error
during initialization or programming. When in command mode it is possible
to use the flashtool's `-s` option to query Katapult's status which includes
SD Card status:

```
./scripts/flashtool.py -s -u aabbccddeeff
Connecting to CAN UUID aabbccddeeff on interface can0
Resetting all bootloader node IDs...
Detected Klipper binary version v0.12.0-302-g87ac69363, MCU: stm32f103xe
Attempting to connect to bootloader
Katapult Connected
Software Version: v0.0.1-95-g2d7bd0c
Protocol Version: 1.1.0
Block Size: 64 bytes
Application Start: 0x8004000
MCU type: stm32f103xe
Verifying canbus connection

*** SD Card Status ***
Detected SD Card Interface: HARDWARE_SPI
Last SD Flash State: NO_DISK
SD Flags: DEINITIALIZED
Last Error: NO_IDLE_STATE
Status Request Complete
```


## Katapult Deployer

**WARNING**: Make absolutely sure your Katapult build configuration is
Expand Down
24 changes: 24 additions & 0 deletions lib/fatfs/LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FatFs License

FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that heading the source files.

/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem Module Rx.xx /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 20xx, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/ this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/

Therefore FatFs license is one of the BSD-style licenses, but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, do not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses include GNU GPL. When you redistribute the FatFs source code with changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license.
77 changes: 77 additions & 0 deletions lib/fatfs/diskio.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2019 /
/-----------------------------------------------------------------------*/

#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED

#ifdef __cplusplus
extern "C" {
#endif

/* Status of Disk Functions */
typedef BYTE DSTATUS;

/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;


/*---------------------------------------*/
/* Prototypes for disk control functions */


DSTATUS disk_initialize (BYTE pdrv);
DSTATUS disk_status (BYTE pdrv);
DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count);
DRESULT disk_write (BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count);
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);


/* Disk Status Bits (DSTATUS) */

#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */


/* Command code for disk_ioctrl fucntion */

/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */

/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */

/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */

/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */

#ifdef __cplusplus
}
#endif

#endif
Loading