diff --git a/module_dfu/src/dfu.h b/module_dfu/src/dfu.h index 10fb349c..d60f450d 100644 --- a/module_dfu/src/dfu.h +++ b/module_dfu/src/dfu.h @@ -88,7 +88,7 @@ unsigned char DFUcfgDesc[] = { int DFUReportResetState(NULLABLE_RESOURCE(chanend , c_user_cmd)); int DFUDeviceRequests(XUD_ep c_ep0_out, NULLABLE_REFERENCE_PARAM(XUD_ep, ep0_in), REFERENCE_PARAM(USB_SetupPacket_t, sp), - NULLABLE_RESOURCE(chanend, c_user_cmd), unsigned int altInterface, CLIENT_INTERFACE(i_dfu, dfuInterface)); + NULLABLE_RESOURCE(chanend, c_user_cmd), unsigned int altInterface, CLIENT_INTERFACE(i_dfu, dfuInterface), REFERENCE_PARAM(int, reset)); /* Helper function for C */ void DFUDelay(unsigned d); diff --git a/module_dfu/src/dfu.xc b/module_dfu/src/dfu.xc index c3170ba0..0115db24 100644 --- a/module_dfu/src/dfu.xc +++ b/module_dfu/src/dfu.xc @@ -10,7 +10,7 @@ #include -static int DFU_state = STATE_APP_IDLE; +static int g_DFU_state = STATE_APP_IDLE; static int DFU_status = DFU_OK; static timer DFUTimer; static unsigned int DFUTimerStart = 0; @@ -39,13 +39,19 @@ void temp() asm(".globl DFU_reset_override"); } -static int DFU_OpenFlash(chanend ?c_user_cmd) +/* Return non-zero on error */ +static int DFU_OpenFlash() { if (!DFU_flash_connected) { unsigned int cmd_data[16]; DFUCustomFlashEnable(); - flash_cmd_init(); + int error = flash_cmd_init(); + if(error) + { + return error; + } + DFU_flash_connected = 1; } @@ -64,14 +70,13 @@ static int DFU_CloseFlash(chanend ?c_user_cmd) return 0; } -static int DFU_Detach(unsigned int timeout, chanend ?c_user_cmd) +static int DFU_Detach(unsigned int timeout, chanend ?c_user_cmd, unsigned &DFU_state) { if (DFU_state == STATE_APP_IDLE) { - DFU_state = STATE_APP_DETACH; - DFU_OpenFlash(c_user_cmd); + DFU_OpenFlash(); // Setup DFU timeout value DFUResetTimeout = timeout * 100000; @@ -86,16 +91,20 @@ static int DFU_Detach(unsigned int timeout, chanend ?c_user_cmd) return 0; } -static int DFU_Dnload(unsigned int request_len, unsigned int block_num, const unsigned request_data[16], chanend ?c_user_cmd) +static int DFU_Dnload(unsigned int request_len, unsigned int block_num, const unsigned request_data[16], chanend ?c_user_cmd, int &return_data_len, unsigned &DFU_state) { unsigned int fromDfuIdle = 0; - + return_data_len = 0; + int error; // Get DFU packets here, sequence is // DFU_DOWNLOAD -> DFU_DOWNLOAD_SYNC // GET_STATUS -> DFU_DOWNLOAD_SYNC (flash busy) || DFU_DOWNLOAD_IDLE // REPEAT UNTIL DFU_DOWNLOAD with 0 length -> DFU_MANIFEST_SYNC - DFU_OpenFlash(c_user_cmd); + if((error = DFU_OpenFlash())) + { + return error; + } switch (DFU_state) { @@ -104,13 +113,13 @@ static int DFU_Dnload(unsigned int request_len, unsigned int block_num, const un break; default: DFU_state = STATE_DFU_ERROR; - return 0; + return 1; } if ((DFU_state == STATE_DFU_IDLE) && (request_len == 0)) { DFU_state = STATE_DFU_ERROR; - return 0; + return 1; } else if (DFU_state == STATE_DFU_IDLE) { @@ -178,7 +187,7 @@ static int DFU_Dnload(unsigned int request_len, unsigned int block_num, const un } -static int DFU_Upload(unsigned int request_len, unsigned int block_num, unsigned data_out[16], chanend ?c_user_cmd) +static int DFU_Upload(unsigned int request_len, unsigned int block_num, unsigned data_out[16], unsigned &DFU_state) { unsigned int cmd_data[16]; unsigned int firstRead = 0; @@ -186,7 +195,7 @@ static int DFU_Upload(unsigned int request_len, unsigned int block_num, unsigned // Start at flash address 0 // Keep reading flash pages until read_page returns 1 (address out of range) // Return terminating upload packet at this point - DFU_OpenFlash(c_user_cmd); + DFU_OpenFlash(); switch (DFU_state) { @@ -237,7 +246,7 @@ static int DFU_Upload(unsigned int request_len, unsigned int block_num, unsigned return 64; } -static int DFU_GetStatus(unsigned int request_len, unsigned data_buffer[16], chanend ?c_user_cmd) +static int DFU_GetStatus(unsigned int request_len, unsigned data_buffer[16], chanend ?c_user_cmd, unsigned &DFU_state) { unsigned int timeout = 0; @@ -270,7 +279,7 @@ static int DFU_GetStatus(unsigned int request_len, unsigned data_buffer[16], cha } -static int DFU_ClrStatus(void) +static int DFU_ClrStatus(unsigned &DFU_state) { if (DFU_state == STATE_DFU_ERROR) { @@ -283,9 +292,8 @@ static int DFU_ClrStatus(void) return 0; } -static int DFU_GetState(unsigned int request_len, unsigned int request_data[16], chanend ?c_user_cmd) +static int DFU_GetState(unsigned int request_len, unsigned int request_data[16], chanend ?c_user_cmd, unsigned &DFU_state) { - request_data[0] = DFU_state; switch (DFU_state) @@ -302,7 +310,7 @@ static int DFU_GetState(unsigned int request_len, unsigned int request_data[16], return 1; } -static int DFU_Abort(void) +static int DFU_Abort(unsigned &DFU_state) { DFU_state = STATE_DFU_IDLE; return 0; @@ -318,20 +326,20 @@ int DFUReportResetState(chanend ?c_user_cmd) { unsigned int cmd_data[16]; inDFU = 1; - DFU_state = STATE_DFU_IDLE; + g_DFU_state = STATE_DFU_IDLE; return inDFU; } - switch(DFU_state) + switch(g_DFU_state) { case STATE_APP_DETACH: case STATE_DFU_IDLE: - DFU_state = STATE_DFU_IDLE; + g_DFU_state = STATE_DFU_IDLE; DFUTimer :> currentTime; if (currentTime - DFUTimerStart > DFUResetTimeout) { - DFU_state = STATE_APP_IDLE; + g_DFU_state = STATE_APP_IDLE; inDFU = 0; } else @@ -349,10 +357,10 @@ int DFUReportResetState(chanend ?c_user_cmd) case STATE_DFU_UPLOAD_IDLE: case STATE_DFU_ERROR: inDFU = 0; - DFU_state = STATE_APP_IDLE; + g_DFU_state = STATE_APP_IDLE; break; default: - DFU_state = STATE_DFU_ERROR; + g_DFU_state = STATE_DFU_ERROR; inDFU = 1; break; } @@ -369,7 +377,7 @@ static int XMOS_DFU_RevertFactory(chanend ?c_user_cmd) { unsigned s = 0; - DFU_OpenFlash(c_user_cmd); + DFU_OpenFlash(); flash_cmd_erase_all(); @@ -403,54 +411,71 @@ void DFUHandler(server interface i_dfu i, chanend ?c_user_cmd) { select { - case i.HandleDfuRequest(USB_SetupPacket_t &sp, unsigned data_buffer[], unsigned data_buffer_length) - -> {unsigned reset_device_after_ack, int return_data_len, unsigned dfu_reset_override}: + case i.HandleDfuRequest(USB_SetupPacket_t &sp, unsigned data_buffer[], unsigned data_buffer_length, unsigned dfuState) + -> {unsigned reset_device_after_ack, int return_data_len, unsigned dfu_reset_override, unsigned returnVal, unsigned newDfuState}: reset_device_after_ack = 0; return_data_len = 0; dfu_reset_override = 0; + unsigned tmpDfuState; + returnVal = 0; // Map Standard DFU commands onto device level firmware upgrade mechanism switch (sp.bRequest) { case DFU_DETACH: - return_data_len = DFU_Detach(sp.wValue, c_user_cmd); + tmpDfuState = dfuState; + return_data_len = DFU_Detach(sp.wValue, c_user_cmd, tmpDfuState); + newDfuState = tmpDfuState;; break; case DFU_DNLOAD: unsigned data[16]; for(int i = 0; i < 16; i++) data[i] = data_buffer[i]; - return_data_len = DFU_Dnload(sp.wLength, sp.wValue, data, c_user_cmd); + tmpDfuState = dfuState; + returnVal = DFU_Dnload(sp.wLength, sp.wValue, data, c_user_cmd, return_data_len, tmpDfuState); + newDfuState = tmpDfuState; + break; case DFU_UPLOAD: unsigned data_out[16]; - return_data_len = DFU_Upload(sp.wLength, sp.wValue, data_out, c_user_cmd); + tmpDfuState = dfuState; + return_data_len = DFU_Upload(sp.wLength, sp.wValue, data_out, tmpDfuState); + newDfuState = tmpDfuState; for(int i = 0; i < 16; i++) data_buffer[i] = data_out[i]; break; case DFU_GETSTATUS: unsigned data_out[16]; - return_data_len = DFU_GetStatus(sp.wLength, data_out, c_user_cmd); + tmpDfuState = dfuState; + return_data_len = DFU_GetStatus(sp.wLength, data_out, c_user_cmd, tmpDfuState); + newDfuState = tmpDfuState; for(int i = 0; i < 16; i++) data_buffer[i] = data_out[i]; break; case DFU_CLRSTATUS: - return_data_len = DFU_ClrStatus(); + tmpDfuState = dfuState; + return_data_len = DFU_ClrStatus(tmpDfuState); + newDfuState = tmpDfuState; break; case DFU_GETSTATE: unsigned data_out[16]; - return_data_len = DFU_GetState(sp.wLength, data_out, c_user_cmd); + tmpDfuState = dfuState; + return_data_len = DFU_GetState(sp.wLength, data_out, c_user_cmd, tmpDfuState); + newDfuState = tmpDfuState; for(int i = 0; i < 16; i++) data_buffer[i] = data_out[i]; break; case DFU_ABORT: - return_data_len = DFU_Abort(); + tmpDfuState = dfuState; + return_data_len = DFU_Abort(tmpDfuState); + newDfuState = tmpDfuState; break; /* XMOS Custom DFU requests */ @@ -500,12 +525,14 @@ void DFUHandler(server interface i_dfu i, chanend ?c_user_cmd) } } -int DFUDeviceRequests_(client interface i_dfu i, XUD_ep ep0_out, XUD_ep &?ep0_in, USB_SetupPacket_t &sp, unsigned int altInterface) +int DFUDeviceRequests(XUD_ep ep0_out, XUD_ep &?ep0_in, USB_SetupPacket_t &sp, chanend ?c_user_cmd, unsigned int altInterface, client interface i_dfu i,int &reset) { unsigned int return_data_len = 0; unsigned int data_buffer_len = 0; unsigned int data_buffer[17]; unsigned int reset_device_after_ack = 0; + unsigned int returnVal = 0; + unsigned int dfuState = g_DFU_state; if(sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_H2D) { @@ -515,42 +542,29 @@ int DFUDeviceRequests_(client interface i_dfu i, XUD_ep ep0_out, XUD_ep &?ep0_in } /* Interface used here such that the handler can be on another tile */ - {reset_device_after_ack, return_data_len, DFU_reset_override} = i.HandleDfuRequest(sp, data_buffer, data_buffer_len); + {reset_device_after_ack, return_data_len, DFU_reset_override, returnVal, dfuState} = i.HandleDfuRequest(sp, data_buffer, data_buffer_len, g_DFU_state); - if (sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_D2H && sp.wLength != 0) + /* Update our version of dfuState */ + g_DFU_state = dfuState; + + /* Check if the request was handled */ + if(!returnVal) { - XUD_DoGetRequest(ep0_out, ep0_in, (data_buffer, unsigned char[]), return_data_len, return_data_len); - } - else - { - XUD_DoSetRequestStatus(ep0_in); - } + if (sp.bmRequestType.Direction == USB_BM_REQTYPE_DIRECTION_D2H && sp.wLength != 0) + { + XUD_DoGetRequest(ep0_out, ep0_in, (data_buffer, unsigned char[]), return_data_len, return_data_len); + } + else + { + XUD_DoSetRequestStatus(ep0_in); + } - // If device reset requested, handle after command acknowledgement - if (reset_device_after_ack) - { - return 1; - } - - return 0; + // If device reset requested, handle after command acknowledgement + if (reset_device_after_ack) + { + reset = 1; + } + } + return returnVal; } -int DFUDeviceRequests(XUD_ep ep0_out, XUD_ep &?ep0_in, USB_SetupPacket_t &sp, chanend ?c_user_cmd, unsigned int altInterface, client interface i_dfu i) -{ - //interface i_dfu i; - int retVal; - - // par - // { -//#if XUD_TILE == 0 - // /* Flash is always on tile 0, USB may be used on a different tile */ - // [[distribute]] - // DFUHandler(i, c_user_cmd); -//#else -//#error -//#endif - retVal = DFUDeviceRequests_(i, ep0_out, ep0_in, sp, altInterface); - // } - - return retVal; -} diff --git a/module_dfu/src/dfu_interface.h b/module_dfu/src/dfu_interface.h index 60169833..45461147 100644 --- a/module_dfu/src/dfu_interface.h +++ b/module_dfu/src/dfu_interface.h @@ -6,8 +6,8 @@ interface i_dfu { - {unsigned, int, unsigned} HandleDfuRequest(USB_SetupPacket_t &sp, unsigned data_buffer[], unsigned data_buffer_length); - void finish(); + {unsigned, int, unsigned, unsigned, unsigned} HandleDfuRequest(USB_SetupPacket_t &sp, unsigned data_buffer[], unsigned data_buffer_length, unsigned dfuState); + void finish(); }; #endif diff --git a/module_dfu/src/flash_interface.c b/module_dfu/src/flash_interface.c index 245f6b1b..4aeb285c 100755 --- a/module_dfu/src/flash_interface.c +++ b/module_dfu/src/flash_interface.c @@ -40,6 +40,7 @@ void DFUCustomFlashDisable() return; } +/* Returns non-zero for error */ int flash_cmd_init(void) { fl_BootImageInfo image; @@ -51,7 +52,9 @@ int flash_cmd_init(void) } if (!flash_device_open) - return 0; + { + return 1; + } #ifndef QUAD_SPI_FLASH // Disable flash protection @@ -59,8 +62,8 @@ int flash_cmd_init(void) #endif if (fl_getFactoryImage(&image) != 0) - { - return 0; + { + return 1; } factory_image = image; diff --git a/module_usb_audio/audio.h b/module_usb_audio/audio.h index 9560980c..271def28 100644 --- a/module_usb_audio/audio.h +++ b/module_usb_audio/audio.h @@ -2,6 +2,7 @@ #define __audio_h__ #include "devicedefines.h" +#include "dfu_interface.h" /** The audio driver thread. * * This function drives I2S ports and handles samples to/from other digital @@ -21,7 +22,11 @@ void audio(chanend c_in, #if(defined(SPDIF_RX) || defined(ADAT_RX)) chanend c_dig, #endif - chanend ?c_config, chanend ?c_adc); + chanend ?c_config, chanend ?c_adc +#if (XUD_TILE != 0) + , server interface i_dfu dfuInterface +#endif +); void SpdifTxWrapper(chanend c_spdif_tx); diff --git a/module_usb_audio/audio.xc b/module_usb_audio/audio.xc index f35bb940..49ab6455 100755 --- a/module_usb_audio/audio.xc +++ b/module_usb_audio/audio.xc @@ -14,6 +14,8 @@ #include #include "devicedefines.h" + +#include "dfu_interface.h" #include "audioports.h" #include "audiohw.h" #ifdef SPDIF_TX @@ -866,46 +868,69 @@ void SpdifTxWrapper(chanend c_spdif_tx) /* This function is a dummy version of the deliver thread that does not connect to the codec ports. It is used during DFU reset. */ + +[[distributable]] +void DFUHandler(server interface i_dfu i, chanend ?c_user_cmd); + +#pragma select handler +void testct_byref(chanend c, int &returnVal) +{ + returnVal = 0; + if(testct(c)) + returnVal = 1; +} + + unsigned static dummy_deliver(chanend c_out) { + int ct; + + outuint(c_out, 0); + while (1) { - outuint(c_out, 0); - - /* Check for sample freq change or new samples from mixer*/ - if(testct(c_out)) - { - unsigned command = inct(c_out); - return command; - } - else + select { + /* Check for sample freq change or new samples from mixer*/ + case testct_byref(c_out, ct): + if(ct) + { + + unsigned command = inct(c_out); + return command; + } + else + { #ifndef MIXER // Interfaces straight to decouple() - (void) inuint(c_out); + (void) inuint(c_out); #pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_IN; i++) - { - outuint(c_out, 0); - } + for(int i = 0; i < NUM_USB_CHAN_IN; i++) + { + outuint(c_out, 0); + } #pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_OUT; i++) - { - (void) inuint(c_out); - } + for(int i = 0; i < NUM_USB_CHAN_OUT; i++) + { + (void) inuint(c_out); + } #else #pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_OUT; i++) - { - (void) inuint(c_out); - } + for(int i = 0; i < NUM_USB_CHAN_OUT; i++) + { + (void) inuint(c_out); + } #pragma loop unroll - for(int i = 0; i < NUM_USB_CHAN_IN; i++) - { - outuint(c_out, 0); - } + for(int i = 0; i < NUM_USB_CHAN_IN; i++) + { + outuint(c_out, 0); + } #endif + } + + outuint(c_out, 0); + break; } } return 0; @@ -923,7 +948,11 @@ chanend c_spdif_out, #if (defined(ADAT_RX) || defined(SPDIF_RX)) chanend c_dig_rx, #endif -chanend ?c_config, chanend ?c) +chanend ?c_config, chanend ?c +#if XUD_TILE != 0 +, server interface i_dfu dfuInterface +#endif +) { #if defined (SPDIF_TX) && (SPDIF_TX_TILE == AUDIO_IO_TILE) chan c_spdif_out; @@ -1213,8 +1242,12 @@ chanend ?c_config, chanend ?c) while (1) { - - command = dummy_deliver(c_mix_out); + par{ +#if XUD_TILE != 0 + DFUHandler(dfuInterface, null); +#endif + command = dummy_deliver(c_mix_out); + } curSamFreq = inuint(c_mix_out); if (curSamFreq == AUDIO_START_FROM_DFU) diff --git a/module_usb_audio/endpoint0/endpoint0.c b/module_usb_audio/endpoint0/endpoint0.c index 701c17a4..ad5d36d3 100755 --- a/module_usb_audio/endpoint0/endpoint0.c +++ b/module_usb_audio/endpoint0/endpoint0.c @@ -558,6 +558,8 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, if (interfaceNum == DFU_IF) { + int reset = 0; + /* If running in application mode stop audio */ /* Don't interupt audio for save and restore cmds */ if ((DFU_IF == INTERFACE_NUMBER_DFU) && (sp.bRequest != XMOS_DFU_SAVESTATE) && @@ -571,14 +573,16 @@ void Endpoint0(chanend c_ep0_out, chanend c_ep0_in, chanend c_audioControl, } /* This will return 1 if reset requested */ - if (DFUDeviceRequests(ep0_out, &ep0_in, &sp, null, g_interfaceAlt[sp.wIndex], dfuInterface)) + result = DFUDeviceRequests(ep0_out, &ep0_in, &sp, null, g_interfaceAlt[sp.wIndex], dfuInterface, &reset); + + if(reset && result == XUD_RES_OKAY) { DFUDelay(50000000); device_reboot(c_audioControl); } /* TODO we should not make the assumption that all DFU requests are handled */ - result = 0; + //result = 0; } #endif /* Check for: - Audio CONTROL interface request - always 0, note we check for DFU first diff --git a/module_usb_audio/main.xc b/module_usb_audio/main.xc index 93308e2f..686ba3f2 100755 --- a/module_usb_audio/main.xc +++ b/module_usb_audio/main.xc @@ -278,6 +278,7 @@ void usb_audio_core(chanend c_mix_out #endif , chanend ?c_clk_int , chanend ?c_clk_ctl +, client interface i_dfu dfuInterface ) { chan c_sof; @@ -298,13 +299,7 @@ void usb_audio_core(chanend c_mix_out #else #define c_EANativeTransport_ctrl null #endif - -#ifdef DFU - interface i_dfu dfuInterface; -#else - #define dfuInterface null -#endif - + par { /* USB Interface Core */ @@ -376,12 +371,7 @@ void usb_audio_core(chanend c_mix_out /* Endpoint 0 Core */ { thread_speed(); - par - { - [[distribute]] - DFUHandler(dfuInterface, null); - Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface); - } + Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface); } /* Decoupling core */ @@ -409,6 +399,9 @@ void usb_audio_io(chanend c_aud_in, chanend ?c_adc, chanend ?c_adat_rx, chanend ?c_clk_ctl, chanend ?c_clk_int +#if (XUD_TILE != 0) + , server interface i_dfu dfuInterface +#endif ) { #ifdef MIXER @@ -445,7 +438,11 @@ void usb_audio_io(chanend c_aud_in, chanend ?c_adc, #if defined(SPDIF_RX) || defined(ADAT_RX) c_dig_rx, #endif - c_aud_cfg, c_adc); + c_aud_cfg, c_adc +#if XUD_TILE != 0 + ,dfuInterface +#endif + ); } #if defined(SPDIF_RX) || defined(ADAT_RX) @@ -523,25 +520,41 @@ int main() #define c_clk_ctl null #endif +#ifdef DFU + interface i_dfu dfuInterface; +#else + #define dfuInterface null +#endif + + USER_MAIN_DECLARATIONS par - { - on tile[XUD_TILE]: usb_audio_core(c_mix_out + { + on tile[XUD_TILE]: + par + { +#if (XUD_TILE == 0) + /* Check if USB is on the flash tile (tile 0) */ + [[distribute]] + DFUHandler(dfuInterface, null); +#endif + usb_audio_core(c_mix_out #ifdef MIDI - , c_midi + , c_midi #endif #ifdef IAP - , c_iap + , c_iap #ifdef IAP_EA_NATIVE_TRANS - , c_ea_data + , c_ea_data #endif #endif #ifdef MIXER - , c_mix_ctl + , c_mix_ctl #endif - , c_clk_int, c_clk_ctl -); + , c_clk_int, c_clk_ctl, dfuInterface + ); + } on tile[AUDIO_IO_TILE]: usb_audio_io(c_mix_out, c_adc #if defined(SPDIF_TX) && (SPDIF_TX_TILE != AUDIO_IO_TILE) @@ -551,6 +564,10 @@ int main() , c_mix_ctl #endif ,c_aud_cfg, c_spdif_rx, c_adat_rx, c_clk_ctl, c_clk_int +#if XUD_TILE != 0 + , dfuInterface +#endif + ); #if defined(SPDIF_TX) && (SPDIF_TX_TILE != AUDIO_IO_TILE)