Skip to content
Permalink
Browse files

bootloader: enable MPU, introduce delays to USB stack

  • Loading branch information...
prusnak committed Feb 20, 2019
1 parent 0f5c969 commit 22f37e81a3270da5e8e5d6c55abc8f15f3a35567
Showing with 858 additions and 6 deletions.
  1. +1 −0 Makefile
  2. +3 −0 bootloader/bootloader.c
  3. +3 −1 firmware/usb.c
  4. +49 −0 setup.c
  5. +2 −0 setup.h
  6. +3 −1 usb21_standard.c
  7. +161 −0 usb_private.h
  8. +604 −0 usb_standard.c
  9. +19 −0 util.c
  10. +3 −0 util.h
  11. +3 −1 webusb.c
  12. +7 −3 winusb.c
@@ -21,6 +21,7 @@ ifneq ($(EMULATOR),1)
OBJS += timer.o
endif

OBJS += usb_standard.o
OBJS += usb21_standard.o
OBJS += webusb.o
OBJS += winusb.o
@@ -129,6 +129,8 @@ int main(void)
oledInit();
#endif

mpu_config_bootloader();

#ifndef APPVER
// at least one button is unpressed
uint16_t state = gpio_port_read(BTN_PORT);
@@ -147,6 +149,7 @@ int main(void)
timer_init();
}

mpu_config_off();
load_app(signed_firmware);
}
#endif
@@ -259,14 +259,16 @@ static int hid_control_request(usbd_device *dev, struct usb_setup_data *req, uin
(void)complete;
(void)dev;

wait_random();

if ((req->bmRequestType != 0x81) ||
(req->bRequest != USB_REQ_GET_DESCRIPTOR) ||
(req->wValue != 0x2200))
return 0;

debugLog(0, "", "hid_control_request u2f");
*buf = (uint8_t *)hid_report_descriptor_u2f;
*len = MIN(*len, sizeof(hid_report_descriptor_u2f));
*len = MIN_8bits(*len, sizeof(hid_report_descriptor_u2f));
return 1;
}

49 setup.c
@@ -141,6 +141,7 @@ void setupApp(void)
gpio_set_af(GPIOA, GPIO_AF10, GPIO10);
}

#define MPU_RASR_SIZE_32B (0x04UL << MPU_RASR_SIZE_LSB)
#define MPU_RASR_SIZE_1KB (0x09UL << MPU_RASR_SIZE_LSB)
#define MPU_RASR_SIZE_4KB (0x0BUL << MPU_RASR_SIZE_LSB)
#define MPU_RASR_SIZE_8KB (0x0CUL << MPU_RASR_SIZE_LSB)
@@ -161,6 +162,54 @@ void setupApp(void)
#define FLASH_BASE (0x08000000U)
#define SRAM_BASE (0x20000000U)

void mpu_config_off(void)
{
// Disable MPU
MPU_CTRL = 0;

__asm__ volatile("dsb");
__asm__ volatile("isb");
}

void mpu_config_bootloader(void)
{
// Disable MPU
MPU_CTRL = 0;

// Note: later entries overwrite previous ones
// Flash (0x08000000 - 0x0807FFFF, 1 MiB, read-write)
MPU_RBAR = FLASH_BASE | MPU_RBAR_VALID | (0 << MPU_RBAR_REGION_LSB);
MPU_RASR = MPU_RASR_ENABLE | MPU_RASR_ATTR_FLASH | MPU_RASR_SIZE_1MB | MPU_RASR_ATTR_AP_PRW_URW;

// Flash (0x8007FE0 - 0x08007FFF, 32 B, no-access)
MPU_RBAR = (FLASH_BASE + 0x7FE0) | MPU_RBAR_VALID | (1 << MPU_RBAR_REGION_LSB);
MPU_RASR = MPU_RASR_ENABLE | MPU_RASR_ATTR_FLASH | MPU_RASR_SIZE_32B | MPU_RASR_ATTR_AP_PNO_UNO;

// SRAM (0x20000000 - 0x2001FFFF, read-write, execute never)
MPU_RBAR = SRAM_BASE | MPU_RBAR_VALID | (2 << MPU_RBAR_REGION_LSB);
MPU_RASR = MPU_RASR_ENABLE | MPU_RASR_ATTR_SRAM | MPU_RASR_SIZE_128KB | MPU_RASR_ATTR_AP_PRW_URW | MPU_RASR_ATTR_XN;

// Peripherals (0x40000000 - 0x4001FFFF, read-write, execute never)
MPU_RBAR = PERIPH_BASE | MPU_RBAR_VALID | (3 << MPU_RBAR_REGION_LSB);
MPU_RASR = MPU_RASR_ENABLE | MPU_RASR_ATTR_PERIPH | MPU_RASR_SIZE_128KB | MPU_RASR_ATTR_AP_PRW_URW | MPU_RASR_ATTR_XN;
// Peripherals (0x40020000 - 0x40023FFF, read-write, execute never)
MPU_RBAR = 0x40020000 | MPU_RBAR_VALID | (4 << MPU_RBAR_REGION_LSB);
MPU_RASR = MPU_RASR_ENABLE | MPU_RASR_ATTR_PERIPH | MPU_RASR_SIZE_16KB | MPU_RASR_ATTR_AP_PRW_URW | MPU_RASR_ATTR_XN;
// Don't enable DMA controller access
// Peripherals (0x50000000 - 0x5007ffff, read-write, execute never)
MPU_RBAR = 0x50000000 | MPU_RBAR_VALID | (5 << MPU_RBAR_REGION_LSB);
MPU_RASR = MPU_RASR_ENABLE | MPU_RASR_ATTR_PERIPH | MPU_RASR_SIZE_512KB | MPU_RASR_ATTR_AP_PRW_URW | MPU_RASR_ATTR_XN;

// Enable MPU
MPU_CTRL = MPU_CTRL_ENABLE | MPU_CTRL_HFNMIENA;

// Enable memory fault handler
SCB_SHCSR |= SCB_SHCSR_MEMFAULTENA;

__asm__ volatile("dsb");
__asm__ volatile("isb");
}

// Never use in bootloader! Disables access to PPB (including MPU, NVIC, SCB)
void mpu_config_firmware(void)
{
@@ -27,6 +27,8 @@ extern uint32_t __stack_chk_guard;
void setup(void);
void setupApp(void);

void mpu_config_off(void);
void mpu_config_bootloader(void);
void mpu_config_firmware(void);

#endif
@@ -62,13 +62,15 @@ static int usb21_standard_get_descriptor(usbd_device* usbd_dev,
(void)complete;
(void)usbd_dev;

wait_random();

if (req->bRequest == USB_REQ_GET_DESCRIPTOR) {
int descr_type = req->wValue >> 8;
if (descr_type == USB_DT_BOS) {
if (!usb21_bos) {
return USBD_REQ_NOTSUPP;
}
*len = MIN(*len, build_bos_descriptor(usb21_bos, *buf, *len));
*len = MIN_8bits(*len, build_bos_descriptor(usb21_bos, *buf, *len));
return USBD_REQ_HANDLED;
}
}
@@ -0,0 +1,161 @@
/** @defgroup usb_private_defines USB Private Structures
@brief <b>Defined Constants and Types for the USB Private Structures</b>
@ingroup USB_defines
@version 1.0.0
@author @htmlonly &copy; @endhtmlonly 2010
Gareth McMullin <gareth@blacksphere.co.nz>
@date 10 March 2013
LGPL License Terms @ref lgpl_license
*/

/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
*
* This library is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/

/**@{*/

#ifndef __USB_PRIVATE_H
#define __USB_PRIVATE_H

#define MAX_USER_CONTROL_CALLBACK 4
#define MAX_USER_SET_CONFIG_CALLBACK 4

/** Internal collection of device information. */
struct _usbd_device {
const struct usb_device_descriptor *desc;
const struct usb_config_descriptor *config;
const char **strings;
int num_strings;

uint8_t *ctrl_buf; /**< Internal buffer used for control transfers */
uint16_t ctrl_buf_len;

uint8_t current_address;
uint8_t current_config;

uint16_t pm_top; /**< Top of allocated endpoint buffer memory */

/* User callback functions for various USB events */
void (*user_callback_reset)(void);
void (*user_callback_suspend)(void);
void (*user_callback_resume)(void);
void (*user_callback_sof)(void);

struct usb_control_state {
enum {
IDLE, STALLED,
DATA_IN, LAST_DATA_IN, STATUS_IN,
DATA_OUT, LAST_DATA_OUT, STATUS_OUT,
} state;
struct usb_setup_data req __attribute__((aligned(4)));
uint8_t *ctrl_buf;
uint16_t ctrl_len;
usbd_control_complete_callback complete;
bool needs_zlp;
} control_state;

struct user_control_callback {
usbd_control_callback cb;
uint8_t type;
uint8_t type_mask;
} user_control_callback[MAX_USER_CONTROL_CALLBACK];

usbd_endpoint_callback user_callback_ctr[8][3];

/* User callback function for some standard USB function hooks */
usbd_set_config_callback user_callback_set_config[MAX_USER_SET_CONFIG_CALLBACK];

usbd_set_altsetting_callback user_callback_set_altsetting;

const struct _usbd_driver *driver;

/* private driver data */

uint16_t fifo_mem_top;
uint16_t fifo_mem_top_ep0;
uint8_t force_nak[4];
/*
* We keep a backup copy of the out endpoint size registers to restore
* them after a transaction.
*/
uint32_t doeptsiz[4];
/*
* Received packet size for each endpoint. This is assigned in
* stm32f107_poll() which reads the packet status push register GRXSTSP
* for use in stm32f107_ep_read_packet().
*/
uint16_t rxbcnt;
};

enum _usbd_transaction {
USB_TRANSACTION_IN,
USB_TRANSACTION_OUT,
USB_TRANSACTION_SETUP,
};

/* Do not appear to belong to the API, so are omitted from docs */
/**@}*/

void _usbd_control_in(usbd_device *usbd_dev, uint8_t ea);
void _usbd_control_out(usbd_device *usbd_dev, uint8_t ea);
void _usbd_control_setup(usbd_device *usbd_dev, uint8_t ea);

int _usbd_standard_request_device(usbd_device *usbd_dev,
struct usb_setup_data *req, uint8_t **buf,
uint16_t *len);
int _usbd_standard_request_interface(usbd_device *usbd_dev,
struct usb_setup_data *req, uint8_t **buf,
uint16_t *len);
int _usbd_standard_request_endpoint(usbd_device *usbd_dev,
struct usb_setup_data *req, uint8_t **buf,
uint16_t *len);
int _usbd_standard_request(usbd_device *usbd_dev, struct usb_setup_data *req,
uint8_t **buf, uint16_t *len);

void _usbd_reset(usbd_device *usbd_dev);

/* Functions provided by the hardware abstraction. */
struct _usbd_driver {
usbd_device *(*init)(void);
void (*set_address)(usbd_device *usbd_dev, uint8_t addr);
void (*ep_setup)(usbd_device *usbd_dev, uint8_t addr, uint8_t type,
uint16_t max_size, usbd_endpoint_callback cb);
void (*ep_reset)(usbd_device *usbd_dev);
void (*ep_stall_set)(usbd_device *usbd_dev, uint8_t addr,
uint8_t stall);
void (*ep_nak_set)(usbd_device *usbd_dev, uint8_t addr, uint8_t nak);
uint8_t (*ep_stall_get)(usbd_device *usbd_dev, uint8_t addr);
uint16_t (*ep_write_packet)(usbd_device *usbd_dev, uint8_t addr,
const void *buf, uint16_t len);
uint16_t (*ep_read_packet)(usbd_device *usbd_dev, uint8_t addr,
void *buf, uint16_t len);
void (*poll)(usbd_device *usbd_dev);
void (*disconnect)(usbd_device *usbd_dev, bool disconnected);
uint32_t base_address;
bool set_address_before_status;
uint16_t rx_fifo_size;
};

#endif

0 comments on commit 22f37e8

Please sign in to comment.
You can’t perform that action at this time.