I've been using an XU216-512-TQ128 on a custom development board for several months now with no issues whatsoever. My most recent requirement was to try to find a way to reboot the chip via firmware. After trying a few functions I found in this forum and in lib_usb, I can no longer use the USB PHY on my chip. This happened on 2 of my custom development boards. Details below:
Initially, I searched the forum and found this thread:
xcore.com: Reboot/Reset possible?
which suggested using the following:
Code: Select all
void chipReset(void)
{
unsigned x;
read_sswitch_reg(get_core_id(), 6, x);
write_sswitch_reg(get_core_id(), 6, x);
}
However, the USB PHY was still functional after testing this function. I could run firmware over xTAG via the development tools and manually cycle the power to the custom development board to boot into previously flashed firmware. In each case, my computer enumerated the custom development as expected.
After researching how to reboot the chip via software further, I began browsing the lib_usb package and I found this function in lib_usb/src/endpoint0/device_reboot.xc
Code: Select all
// Copyright (c) 2016, XMOS Ltd, All rights reserved
#include <xs1.h>
#include <platform.h>
#include <xs1_su.h>
#include "xud.h"
#define XS1_SU_PERIPH_USB_ID 0x1
void do_device_reboot(void)
{
// This hack is for a bug in xTIMEcomposer 13.2.0 where write_periph_32 and read_periph32 do not have the correct settings for use in combinable
asm(".globl read_periph_32.locnoside;.globl read_periph_32.locnochandec;.globl read_periph_32.locnoglobalaccess;.globl read_periph_32.locnointerfaceaccess;.globl read_periph_32.locnonotificationselect;.weak read_periph_32.locnoside;.weak read_periph_32.locnochandec;.weak read_periph_32.locnoglobalaccess;.weak read_periph_32.locnointerfaceaccess;.weak read_periph_32.locnonotificationselect;.set read_periph_32.locnoside, 1;.set read_periph_32.locnochandec, 1;.set read_periph_32.locnoglobalaccess, 1;.set read_periph_32.locnointerfaceaccess, 1;.set read_periph_32.locnonotificationselect, 1");
asm(".globl write_periph_32.locnoside;.globl write_periph_32.locnochandec;.globl write_periph_32.locnoglobalaccess;.globl write_periph_32.locnointerfaceaccess;.globl write_periph_32.locnonotificationselect;.weak write_periph_32.locnoside;.weak write_periph_32.locnochandec;.weak write_periph_32.locnoglobalaccess;.weak write_periph_32.locnointerfaceaccess;.weak write_periph_32.locnonotificationselect;.set write_periph_32.locnoside, 1;.set write_periph_32.locnochandec, 1;.set write_periph_32.locnoglobalaccess, 1;.set write_periph_32.locnointerfaceaccess, 1;.set write_periph_32.locnonotificationselect, 1");
asm(".globl write_sswitch_reg.locnoside;.globl write_sswitch_reg.locnochandec;.globl write_sswitch_reg.locnoglobalaccess;.globl write_sswitch_reg.locnointerfaceaccess;.globl write_sswitch_reg.locnonotificationselect;.weak write_sswitch_reg.locnoside;.weak write_sswitch_reg.locnochandec;.weak write_sswitch_reg.locnoglobalaccess;.weak write_sswitch_reg.locnointerfaceaccess;.weak write_sswitch_reg.locnonotificationselect;.set write_sswitch_reg.locnoside, 1;.set write_sswitch_reg.locnochandec, 1;.set write_sswitch_reg.locnoglobalaccess, 1;.set write_sswitch_reg.locnointerfaceaccess, 1;.set write_sswitch_reg.locnonotificationselect, 1");
asm(".globl read_sswitch_reg.locnoside;.globl read_sswitch_reg.locnochandec;.globl read_sswitch_reg.locnoglobalaccess;.globl read_sswitch_reg.locnointerfaceaccess;.globl read_sswitch_reg.locnonotificationselect;.weak read_sswitch_reg.locnoside;.weak read_sswitch_reg.locnochandec;.weak read_sswitch_reg.locnoglobalaccess;.weak read_sswitch_reg.locnointerfaceaccess;.weak read_sswitch_reg.locnonotificationselect;.set read_sswitch_reg.locnoside, 1;.set read_sswitch_reg.locnochandec, 1;.set read_sswitch_reg.locnoglobalaccess, 1;.set read_sswitch_reg.locnointerfaceaccess, 1;.set read_sswitch_reg.locnonotificationselect, 1");
asm(".globl write_sswitch_reg_no_ack.locnoside;.globl write_sswitch_reg_no_ack.locnochandec;.globl write_sswitch_reg_no_ack.locnoglobalaccess;.globl write_sswitch_reg_no_ack.locnointerfaceaccess;.globl write_sswitch_reg_no_ack.locnonotificationselect;.weak write_sswitch_reg_no_ack.locnoside;.weak write_sswitch_reg_no_ack.locnochandec;.weak write_sswitch_reg_no_ack.locnoglobalaccess;.weak write_sswitch_reg_no_ack.locnointerfaceaccess;.weak write_sswitch_reg_no_ack.locnonotificationselect;.set write_sswitch_reg_no_ack.locnoside, 1;.set write_sswitch_reg_no_ack.locnochandec, 1;.set write_sswitch_reg_no_ack.locnoglobalaccess, 1;.set write_sswitch_reg_no_ack.locnointerfaceaccess, 1;.set write_sswitch_reg_no_ack.locnonotificationselect, 1");
asm(".globl write_node_config_reg.locnoside;.globl write_node_config_reg.locnochandec;.globl write_node_config_reg.locnoglobalaccess;.globl write_node_config_reg.locnointerfaceaccess;.globl write_node_config_reg.locnonotificationselect;.weak write_node_config_reg.locnoside;.weak write_node_config_reg.locnochandec;.weak write_node_config_reg.locnoglobalaccess;.weak write_node_config_reg.locnointerfaceaccess;.weak write_node_config_reg.locnonotificationselect;.set write_node_config_reg.locnoside, 1;.set write_node_config_reg.locnochandec, 1;.set write_node_config_reg.locnoglobalaccess, 1;.set write_node_config_reg.locnointerfaceaccess, 1;.set write_node_config_reg.locnonotificationselect, 1");
asm(".globl get_local_tile_id.locnoside;.globl get_local_tile_id.locnochandec;.globl get_local_tile_id.locnoglobalaccess;.globl get_local_tile_id.locnointerfaceaccess;.globl get_local_tile_id.locnonotificationselect;.weak get_local_tile_id.locnoside;.weak get_local_tile_id.locnochandec;.weak get_local_tile_id.locnoglobalaccess;.weak get_local_tile_id.locnointerfaceaccess;.weak get_local_tile_id.locnonotificationselect;.set get_local_tile_id.locnoside, 1;.set get_local_tile_id.locnochandec, 1;.set get_local_tile_id.locnoglobalaccess, 1;.set get_local_tile_id.locnointerfaceaccess, 1;.set get_local_tile_id.locnonotificationselect, 1");
#if (XUD_SERIES_SUPPORT == XUD_U_SERIES)
/* Disconnect from bus */
unsigned data[] = {4};
write_periph_32(usb_tile, XS1_SU_PERIPH_USB_ID, XS1_SU_PER_UIFM_FUNC_CONTROL_NUM, 1, data);
/* Ideally we would reset SU1 here but then we loose power to the xcore and therefore the DFU flag */
/* Disable USB and issue reset to xcore only - not analogue chip */
write_node_config_reg(usb_tile, XS1_SU_CFG_RST_MISC_NUM,0b10);
#else
unsigned int pllVal;
unsigned int localTileId = get_local_tile_id();
unsigned int tileId;
unsigned int tileArrayLength;
/* Find size of tile array - note in future tools versions this will be available from platform.h */
asm volatile ("ldc %0, tile.globound":"=r"(tileArrayLength));
/* Reset all remote tiles */
for(int i = 0; i< tileArrayLength; i++)
{
/* Cannot cast tileref to unsigned! */
tileId = get_tile_id(tile[i]);
/* Do not reboot local tile yet! */
if(localTileId != tileId)
{
read_sswitch_reg(tileId, 6, pllVal);
write_sswitch_reg_no_ack(tileId, 6, pllVal);
}
}
/* Finally reboot this tile! */
read_sswitch_reg(localTileId, 6, pllVal);
write_sswitch_reg_no_ack(localTileId, 6, pllVal);
#endif
}
On the other had, everything else about the chip seems to be OK. I can connect my board to the xTAG adapter and xTimeComposer is able to detect both the xTAG adapter AND the chip it is connected to. The IDE is still able to debug firmware on the target chip. The issue seems limited to only the USB PHY.
While most people would assume this was a hardware failure maybe due to ESD, I find it quite odd that I have been using both boards over the past few months yet I reproduced the exact same failure mode on two custom development boards calling the same function.
So my ultimate question before I go through the trouble of attempting to get these boards reworked is: given the code I posted, is it possible to kill the USB PHY via firmware? In other words, is there a way to disable the USB PHY (which I might have done) and re-enable it? I'm not familiar with assembly, so the first half of the do_device reboot function is unsettling.
Thanks!