usb: dfu: Signal completion of DFU
Generally when DFU is in progress, the system is not expected to be doing anything else in addition. Hence, a completion signal would help the system to know that DFU is over and it can proceed towards next tasks. Signed-off-by: Rajavardhan Gundi <rajavardhan.gundi@intel.com>
This commit is contained in:
parent
c58b637f26
commit
fa49e3e4c7
3 changed files with 68 additions and 0 deletions
|
@ -119,4 +119,6 @@ enum dfu_state {
|
||||||
dfuERROR,
|
dfuERROR,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void wait_for_usb_dfu(void);
|
||||||
|
|
||||||
#endif /* ZEPHYR_INCLUDE_USB_CLASS_USB_DFU_H_ */
|
#endif /* ZEPHYR_INCLUDE_USB_CLASS_USB_DFU_H_ */
|
||||||
|
|
|
@ -126,10 +126,18 @@ source "subsys/usb/class/hid/Kconfig"
|
||||||
config USB_DFU_CLASS
|
config USB_DFU_CLASS
|
||||||
bool "USB DFU Class Driver"
|
bool "USB DFU Class Driver"
|
||||||
select MPU_ALLOW_FLASH_WRITE
|
select MPU_ALLOW_FLASH_WRITE
|
||||||
|
select POLL
|
||||||
depends on IMG_MANAGER
|
depends on IMG_MANAGER
|
||||||
help
|
help
|
||||||
USB DFU class driver
|
USB DFU class driver
|
||||||
|
|
||||||
|
config USB_DFU_WAIT_DELAY_MS
|
||||||
|
int
|
||||||
|
depends on USB_DFU_CLASS
|
||||||
|
default 12000
|
||||||
|
help
|
||||||
|
A thread can wait for a prescribed time (in ms) for DFU to begin
|
||||||
|
|
||||||
config USB_DFU_MAX_XFER_SIZE
|
config USB_DFU_MAX_XFER_SIZE
|
||||||
int
|
int
|
||||||
depends on USB_DFU_CLASS
|
depends on USB_DFU_CLASS
|
||||||
|
|
|
@ -68,6 +68,15 @@ LOG_MODULE_REGISTER(usb_dfu);
|
||||||
#define FIRMWARE_IMAGE_0_LABEL "image-1"
|
#define FIRMWARE_IMAGE_0_LABEL "image-1"
|
||||||
#define FIRMWARE_IMAGE_1_LABEL "image-0"
|
#define FIRMWARE_IMAGE_1_LABEL "image-0"
|
||||||
|
|
||||||
|
/* MCUBoot waits for CONFIG_USB_DFU_WAIT_DELAY_MS time in total to let DFU to
|
||||||
|
* be commenced. It intermittently checks every INTERMITTENT_CHECK_DELAY
|
||||||
|
* milliseconds to see if DFU has started.
|
||||||
|
*/
|
||||||
|
#define INTERMITTENT_CHECK_DELAY 50
|
||||||
|
|
||||||
|
static struct k_poll_event dfu_event;
|
||||||
|
static struct k_poll_signal dfu_signal;
|
||||||
|
|
||||||
static struct k_work dfu_work;
|
static struct k_work dfu_work;
|
||||||
|
|
||||||
struct dfu_worker_data_t {
|
struct dfu_worker_data_t {
|
||||||
|
@ -433,6 +442,8 @@ static int dfu_class_handle_req(struct usb_setup_packet *pSetup,
|
||||||
case dfuIDLE:
|
case dfuIDLE:
|
||||||
LOG_DBG("DFU_DNLOAD start");
|
LOG_DBG("DFU_DNLOAD start");
|
||||||
dfu_reset_counters();
|
dfu_reset_counters();
|
||||||
|
k_poll_signal_reset(&dfu_signal);
|
||||||
|
|
||||||
if (dfu_data.flash_area_id !=
|
if (dfu_data.flash_area_id !=
|
||||||
DT_FLASH_AREA_IMAGE_1_ID) {
|
DT_FLASH_AREA_IMAGE_1_ID) {
|
||||||
dfu_data.status = errWRITE;
|
dfu_data.status = errWRITE;
|
||||||
|
@ -453,6 +464,7 @@ static int dfu_class_handle_req(struct usb_setup_packet *pSetup,
|
||||||
dfu_data_worker.worker_len = pSetup->wLength;
|
dfu_data_worker.worker_len = pSetup->wLength;
|
||||||
if (dfu_data_worker.worker_len == 0) {
|
if (dfu_data_worker.worker_len == 0) {
|
||||||
dfu_data.state = dfuMANIFEST_SYNC;
|
dfu_data.state = dfuMANIFEST_SYNC;
|
||||||
|
k_poll_signal_raise(&dfu_signal, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(dfu_data_worker.buf, *data, pSetup->wLength);
|
memcpy(dfu_data_worker.buf, *data, pSetup->wLength);
|
||||||
|
@ -741,6 +753,7 @@ static int usb_dfu_init(struct device *dev)
|
||||||
ARG_UNUSED(dev);
|
ARG_UNUSED(dev);
|
||||||
|
|
||||||
k_work_init(&dfu_work, dfu_work_handler);
|
k_work_init(&dfu_work, dfu_work_handler);
|
||||||
|
k_poll_signal_init(&dfu_signal);
|
||||||
|
|
||||||
#ifndef CONFIG_USB_COMPOSITE_DEVICE
|
#ifndef CONFIG_USB_COMPOSITE_DEVICE
|
||||||
dfu_config.usb_device_description = usb_get_device_descriptor();
|
dfu_config.usb_device_description = usb_get_device_descriptor();
|
||||||
|
@ -772,4 +785,49 @@ static int usb_dfu_init(struct device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function to check if DFU is started.
|
||||||
|
*
|
||||||
|
* @return true if DNBUSY/DNLOAD_IDLE, false otherwise.
|
||||||
|
*/
|
||||||
|
static bool is_dfu_started(void)
|
||||||
|
{
|
||||||
|
if ((dfu_data.state == dfuDNBUSY) ||
|
||||||
|
(dfu_data.state == dfuDNLOAD_IDLE)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function to check and wait while the USB DFU is in progress.
|
||||||
|
*
|
||||||
|
* @return N/A
|
||||||
|
*/
|
||||||
|
void wait_for_usb_dfu(void)
|
||||||
|
{
|
||||||
|
/* Wait for a prescribed duration of time. If DFU hasn't started within
|
||||||
|
* that time, stop waiting and proceed further.
|
||||||
|
*/
|
||||||
|
for (int time = 0;
|
||||||
|
time < (CONFIG_USB_DFU_WAIT_DELAY_MS/INTERMITTENT_CHECK_DELAY);
|
||||||
|
time++) {
|
||||||
|
if (is_dfu_started()) {
|
||||||
|
k_poll_event_init(&dfu_event, K_POLL_TYPE_SIGNAL,
|
||||||
|
K_POLL_MODE_NOTIFY_ONLY, &dfu_signal);
|
||||||
|
|
||||||
|
/* Wait till DFU is complete */
|
||||||
|
if (k_poll(&dfu_event, 1, K_FOREVER) != 0) {
|
||||||
|
LOG_DBG("USB DFU Error");
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INF("USB DFU Completed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
k_sleep(INTERMITTENT_CHECK_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SYS_INIT(usb_dfu_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
SYS_INIT(usb_dfu_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue