how do you access the USBDCD_STATUS register

Status
Not open for further replies.

jrdarrah

Well-known member
I would like to detect if a USB device is connected and it looks like the USBDCD_STATUS register would be a good place to start. From the kinetis.h file I found this.

#define USBDCD_STATUS (*(volatile uint32_t *)0x40035008) // Status register
#define USBDCD_STATUS_ACTIVE ((uint32_t)0x00400000)
#define USBDCD_STATUS_ID ((uint32_t)0x00200000)
#define USBDCD_STATUS_ERR ((uint32_t)0x00100000)
#define USBDCD_STATUS_SEQ_STAT(n) (uint32_t)(((n) & 0x3) << 18)
#define USBDCD_STATUS_SEQ_STAT_MASK ((uint32_t)0x000C0000)
#define USBDCD_STATUS_SEQ_RES(n) (uint32_t)(((n) & 0x3) << 16)
#define USBDCD_STATUS_SEQ_RES_MASK ((uint32_t)0x00030000)

However when I try to access USBDCD_STATUS the sketch hangs in setup and never runs the loop code. Eventually I'd like to directly access the USBDCD_STATUS_SEQ_RES and USBDCD_STATUS_SEQ_STAT fields. How can I read the register value so I can display either on the serial port or on the LCD?

Code:
//runs on teensy 3.2
#include <DFRobot_LCD.h>
//#include <kinetis.h>
// USB Status detection sstudy
// 7/6/21 Jim Darrah
int r,g,b;


String dataValues;
DFRobot_LCD lcd(16,2, LCD_ADDRESS,RGB_ADDRESS); //16 characters and 2 lines of show
 
void setup() {
  unsigned long delayStart = millis();
  Serial.begin(115200);
  while (!Serial && (millis() - delayStart) <= 1000);
  r=0;
  g=255;
  b=0;
  lcd.init();
  // Serial.println(USBDCD_STATUS); // <<<<<<<<<< if I uncomment this line the sketch never enters the loop code
}
void loop() {
 
lcd.setRGB(r, g, b); //Set R,G,B Value
lcd.setCursor(0,0);
lcd.print("SEQ_RES = ");
lcd.setCursor(7,0);
// lcd.print(USBDCD_STATUS_SEQ_RES);
lcd.setCursor(0,1);
lcd.print("SEQ STAT = ");
lcd.setCursor(6,1);
// lcd.print(USBDCD_STATUS_SEQ_STAT);
delay(1);
}
 
This may be a duplicate, for some reason the reply I just did didn't take

I still don't have it working. I did find some information on the nxp website in addition to the "K20 Sub-Family Reference Manual
Supports: MK20DX64VLH7, MK20DX128VLH7, MK20DX256VLH7" document.

This one has some snippets of code and does refer to sample code. "Kinetis Peripheral Module Quick Reference A Compilation of Demonstration Software for Kinetis Modules". search for KQRUG on the nxp website. The code sample zip listed in the document seems to have a name change. Look for KINETIS512_V2_SC.ZIP. I haven't looked at this yet. Where I stand now is the code still hangs when I reference the usbdcd_status register. based on info I found in the KQRUG manual I changed my code to --
Code:
#include <DFRobot_LCD.h>
// #include <kinetis.h>
// USB Status detection sstudy
// 7/6/21 Jim Darrah
int r,g,b;
#define USBDCD_STATUS_SEQ_STAT_SHIFT             18
#define USBDCD_STATUS_SEQ_RES_SHIFT              16
 String dataValues;
int32_t statusWord;
DFRobot_LCD lcd(16,2, LCD_ADDRESS,RGB_ADDRESS); //16 characters and 2 lines of show
 
void setup() {
  unsigned long delayStart = millis();
  Serial.begin(115200);
  while (!Serial && (millis() - delayStart) <= 1000);
  r=0;
  g=255;
  b=0;
  lcd.init();
  Serial.println("A");
  uint8_t u8ChargerType;
  u8ChargerType = (uint8_t)((USBDCD_STATUS & USBDCD_STATUS_SEQ_RES_MASK)>>USBDCD_STATUS_SEQ_RES_SHIFT);
  Serial.println("B");
  Serial.println(u8ChargerType);
  u8ChargerType|= (uint8_t)((USBDCD_STATUS & USBDCD_STATUS_SEQ_STAT_MASK)>>USBDCD_STATUS_SEQ_STAT_SHIFT);
  Serial.println("C");
  Serial.println(u8ChargerType);
}

The USBDCD chapter has a function to return the charger type - standard host, charging host, dedicated charger. For my purposes, I'm okd with the 1st two. I did make some minor modifications based on the location of the SEQ_STAT and SEQ_RES fields.

The function that returns the charger type result is:
UINT8 DCD_GetChargerType(void)
{
UINT8 u8ChargerType;
u8ChargerType = (UINT8)((USBDCD_STATUS & USBDCD_STATUS_SEQ_RES_MASK)>>16);
u8ChargerType|= (UINT8)((USBDCD_STATUS & USBDCD_STATUS_FLAGS_MASK)>>16);
return

I think that the shift for the Status flags should be 18. I couldn't find the field by that name so I used the one in the <kinetis.h> file. I commented it out in my code since it is already included based on the teensyduino installation.

Does anyone out there have an idea why the setup code crashes/locks when it executes

u8ChargerType = (uint8_t)((USBDCD_STATUS & USBDCD_STATUS_SEQ_RES_MASK)>>USBDCD_STATUS_SEQ_RES_SHIFT);

based on my first attempt and this one the common thread is both access USBDCD_STATUS.
 
However when I try to access USBDCD_STATUS the sketch hangs in setup and never runs the loop code.

Look at the SIM_SCGC6 register documented on page 256 in the reference manual, specifically bit 21. My guess is your program is crashing because that bit is at its default 0 setting.

Almost every peripheral in this chip defaults to a low power disabled state at startup. The default startup code turns on all the stuff which is normally used (PWM, GPIO, ADC, etc). Existing libraries enable the peripherals they use. But when you write code to use a part of the chip nothing else is accessing, you need to first enable it before you try to access any of its registers.
 
Thanks for the help. My program doesn't freeze but it also doesn't work as I thought. When this runs I get "USBDCD_STATUS = 0". I was thinking that since the sketch uses the serial over USB that the usb status register would show I was connected to a host or a charging host. All I see is all zeros in the USBDCD_STATUS register. Apparently I have a flaw in my logic, just not sure why it doesn't return data based on an existing usb connected device.

Code:
// USB Status detection sstudy
// 7/6/21 Jim Darrah
#include <kinetis.h>
#define USBDCD_STATUS_SEQ_STAT_SHIFT             18
#define USBDCD_STATUS_SEQ_RES_SHIFT              16
#define SIM_SCGC5_PORTB_MASK                     0x400u
#define SIM_SCGC4_USBOTG_MASK                    0x40000u
#define SIM_SCGC6_USBDCD_MASK                    0x200000u

void setup() {
 /* SIM Configuration */ 
 SIM_SCGC5|=(SIM_SCGC5_PORTB_MASK); // Enable clock for ptb
 SIM_SCGC4|=(SIM_SCGC4_USBOTG_MASK); // USB Clock Gating
 SIM_SCGC6|=(SIM_SCGC6_USBDCD_MASK); // USB Clock Gating
   unsigned long delayStart = millis();
  SerialUSB.begin(115200);
  while (!SerialUSB && (millis() - delayStart) <= 1000);
  SerialUSB.print("USBDCD_STATUS = ");
  SerialUSB.println(USBDCD_STATUS,HEX);
}
void loop() {
 
 }
 
I wanted to close this thread out. The original question was how to detect if a USB device was connected to the teensy. The thread starts with a query on reading the USBDCD_STATUS register. As it turns out, the problem of detecting a USB connected device was posted in the very last entry of this old thread. https://forum.pjrc.com/threads/26039-Detect-USB-connected/page2?highlight=USB0_OTGSTAT

I too have a battery powered device that has some functions available if there is a USB connection I want to check for a USB device before allowing the user to select the function. I tested this code with a standard USB cable and one with the +5V wire cut. In both cases, if the cable is plugged in, USB0_OTGSTAT = 0. Unplugged USB0_OTGSTAT = 1


Code:
#include <DFRobot_LCD.h>
// USB Status detection sstudy
// 7/30/21 Jim Darrah
int r,g,b;
String dataValues;
int32_t statusWord;
DFRobot_LCD lcd(16,2, LCD_ADDRESS,RGB_ADDRESS); //16 characters and 2 lines of show
 
void setup() {
  r=0;
  g=255;
  b=0;
  lcd.init();
} 
void loop() {
  lcd.setRGB(r, g, b); //Set R,G,B Value
  lcd.setCursor(0,0);
  lcd.print("USB0_OTGSTAT");
  lcd.setCursor(14,0);
  //lcd.print(USB0_OTGSTAT,HEX);
  lcd.print(bitRead(USB0_OTGSTAT,5));
  delay(1);
}
 
Status
Not open for further replies.
Back
Top