LUFA XInput Controller Endpoint IN/OUT not working - usb

Intro:
I've been trying (and failing for four entire days straight so far) to get my Atmega32u4 device (Arduino Pro Micro) to emulate an Xbox controller.
It doesn't have to pretend it's an Xbox controller, but I need to communicate with the XInput driver, so emulating an official controller seemed like the best way to start.
The problem:
When using the code example XInputPadMicro by Bootsector it gets me exactly halfway. My device can either read OR write from/to the device driver. But not both. Getting both to work is essential to my project.
The code:
Device/Configuration descriptor can be found in XInputPadMicro (I
haven't changed these).
Configuration changed event:
Enabling the "OUT" endpoint will break the "IN" endpoint.
#define JOYSTICK_EPADDR_IN (ENDPOINT_DIR_IN | 1)
#define JOYSTICK_EPADDR_OUT (ENDPOINT_DIR_OUT | 1)
void EVENT_USB_Device_ConfigurationChanged(void)
{
bool ConfigSuccess = true;
ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR_IN, EP_TYPE_INTERRUPT, 20, 1);
//If I enable this, the "IN" Endpoint will stop sending data.
//ConfigSuccess &= Endpoint_ConfigureEndpoint(JOYSTICK_EPADDR_OUT, EP_TYPE_INTERRUPT, 8, 1);
}
USB control request event:
void EVENT_USB_Device_ControlRequest(void)
{
/* Handle HID Class specific requests */
switch (USB_ControlRequest.bRequest)
{
case HID_REQ_GetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_Write_Control_Stream_LE(&gamepad_state, 20);
Endpoint_ClearIN();
}
break;
case HID_REQ_SetReport:
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
Endpoint_Read_Control_Stream_LE(&RXData, 8);
Endpoint_ClearOUT();
}
break;
}
}
HID Task (called every cycle):
void HID_Task(void)
{
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
Endpoint_SelectEndpoint(JOYSTICK_EPADDR_OUT);
if (Endpoint_IsOUTReceived())
{
toggle = !toggle;
SetLED(LED3, toggle);
Endpoint_Read_Stream_LE(&RXData, 8, NULL);
SetLED(LED1, RXData[3] > 0 || RXData[4] > 0);
Endpoint_ClearOUT();
}
/* Select the Joystick Report Endpoint */
Endpoint_SelectEndpoint(JOYSTICK_EPADDR_IN);
/* Check to see if the host is ready for another packet */
if (Endpoint_IsINReady())
{
/* Write Joystick Report Data */
Endpoint_Write_Stream_LE(&gamepad_state, 20, NULL);
/* Finalize the stream transfer to send the last packet */
Endpoint_ClearIN();
}
}
Am I missing something crucial? Perhaps about the inner workings of the USB protocol? I am at a loss here.

Related

How to optimize the code for reading SPI through ARDUINO in SLAVE mode

Not important:
I am doing a project to integrate a bluetooth module into a car radio pioneer. I understand perfectly well that it's easier to buy a new one =) but it's not interesting. At the moment, the byproduct was an adapter on arduino of resistor buttons, which the pioneer did not understand. The same adapter also controls the bluetooth board, it can switch the track forward and backward (there is no button on the steering wheel for pause). Now I want the bluetooth to turn on only in AUX mode. But there is a problem, which mode can be understood only by reading the signal from the SPI bus of the commutation microcircuit. I was able to read this data using arduino nano. I do not have an analyzer, but it is not necessary that I would understand something additional with it.
Essence of the question:
Using the scientific poke method, I found sequences indicating the launch of a particular mode, for example:
10110011
1
111
1000000
I'm sure I'm doing it wrong, but in the meantime I get duplicate results. But, when I try to detect them using IF, the nano speed is not enough and the chip starts to pass data.
#include "SPI.h"
bool flag01, flag02, flag03, flag11, flag12, flag13, flag31, flag32, flag33;
void setup (void)
{
Serial.begin(9600);
pinMode(MISO, OUTPUT);
SPCR |= _BV(SPE);
SPI.attachInterrupt();
}
// Вызываем функцию обработки прерываний по вектору SPI
// STC - Serial Transfer Comlete
ISR(SPI_STC_vect)
{
// Получаем байт из регистра данных SPI
byte c = SPDR;
Serial.println(c, BIN);
if (c == 0b1) {
Serial.println("1 ok");
flag11 = true;
} else {
flag11 = false;
}
if (c == 0b11 && flag11) {
Serial.println("11 ok");
flag12 = true;
} else {
flag12 = false;
flag11 = false;
}
if (c == 0b1100000 && flag11 && flag12) {
Serial.println("1100000 ok");
flag13 = true;
} else {
flag13 = false;
flag12 = false;
flag11 = false;
}
}
void loop(void)
{}
I myself am scared to look at this code, but I cannot think of anything better. It seems like I heard about some kind of buffer, but I don't know how to screw it to this solution. After all, the data packets go with dropping the CS signal and I can’t figure out how to determine the beginning and end of the packet from the commands in order to write it to a buffer or array and only then go through it with a comparison.
I will be grateful if someone will tell me at least in which direction to move.
There is also esp8266, but there is a limitation on the size of a data packet of 32 bits in a slave mode and I do not know how to get around it correctly.
So, actually the question.
How can I optimize the code so that the arduino has time to process the data and I can catch the pattern?
Perhaps, if we implement reading of data of arbitrary length on esp8266, or at least fill them to the required length, it would help me. But I still can't figure it out with the spi.slave library.
First you should keep your ISR as short as possible, certainly don't use Serial print inside the ISR.
Secondly, if you don't know exactly how long the data is, then you need to have a buffer to capture the data and try to determine the data length first before you trying to analysis it.
volatile uint8_t byteCount = 0;
volatile bool dataReady = false;
byte data[32];
// SPI interrupt routine
ISR (SPI_STC_vect)
{
data[byteCount++] = SPDR;
dataReady = true;
}
void setup (void)
{
// your SPI and Serial setup code
}
void loop (void)
{
// for determine the data stream length
if (dataReady) {
Serial.println(byteCount);
dataReady = false;
}
}
Once you know how long the data stream is (let assumed it is 15-byte long), you can then change your sketch slightly to capture the data and analysis it.
volatile uint8_t byteCount = 0;
volatile bool dataReady = false;
byte data[32];
// SPI interrupt routine
ISR (SPI_STC_vect)
{
data[byteCount++] = SPDR;
if (byteCount == 15)
dataReady = true;
}
void loop (void)
{
if (dataReady) {
dataReady = false;
// do your analysis here
}
}

Using performance monitor unit to generate an interrupt on Xilinx ZynqZC706

I am currently trying to use the performance monitor to generate an interrupt when an overflow of Data Cache misses occurs. I have enabled the pmu and the IRQ for the performance monitor (PMINTENSET is 1 for the counter). I am able to see that the overflow flag is set when the overflow occurs but the interrupt is never triggered. I think I am missing something when setting up the interrupt. I am using Xilinx SDK 2018.2.
I have attached my code for setting up the interrupt:
XScuGic xInterruptController; /* Interrupt controller instance */
static void setup_interrupt(void)
{
uint32_t status;
XScuGic_Config *pxGICConfig;
pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_0_DEVICE_ID );
if (pxGICConfig==NULL)
{
xil_printf("\nERROR LOOKING UP CONFIGURATION");
for(;;);
}
status = XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
if (status != XST_SUCCESS)
{
xil_printf("\nERROR INITIALIZING CONFIGURATION");
for(;;);
}
status = XScuGic_SelfTest(&xInterruptController);
if (status != XST_SUCCESS)
{
xil_printf("\nERROR: SELF TEST FAILURE");
for(;;);
}
/*
* Initialize the exception table.
*/
Xil_ExceptionInit();
status = RegisterInterruptExceptions(&xInterruptController);
if (status != XST_SUCCESS) {
xil_printf("\nERROR: SetUP Interrupt System Failed");
for(;;);
}
status = XScuGic_Connect( &xInterruptController, XPS_PMU0_INT_ID, (Xil_ExceptionHandler) pmuIRQ_handler, ( void * ) &xInterruptController);
if (status!= XST_SUCCESS)
{
xil_printf("\nERROR CONNECTING INTERRUPT");
for(;;);
}
XScuGic_SetPriorityTriggerType(&xInterruptController, XPS_PMU0_INT_ID, 8, 0b10); // Priority 8 (second highest) and high level sensitivity
XScuGic_InterruptMaptoCpu(&xInterruptController, 0, XPS_PMU0_INT_ID);
// Enable the interrupt for the xTimer in the interrupt controller.
XScuGic_Enable( &xInterruptController, XPS_PMU0_INT_ID );
}
int RegisterInterruptExceptions(XScuGic *XScuGicInstancePtr)
{
/*
* Connect the interrupt controller interrupt handler to the hardware
* interrupt handling logic in the ARM processor.
*/
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler,XScuGicInstancePtr);
/*
* Enable interrupts in the ARM
*/
Xil_ExceptionEnable();
return XST_SUCCESS;
}
void pmuIRQ_handler( void *CallbackRef )
{
xil_printf("Interrupt occurred\n");
}
I am not sure if I need to use Vivado to map the PMU interrupt to the GIC? I couldn't find any examples on generating interrupts using the performance monitor. I am currently using the default ZC706 HW platform provided by Xilinx SDK and I am not sure if I need to generate a bitstream in Vivado the maps the PMU to the GIC? I thought that this was done by using XScuGic_InterruptMaptoCpu().
I tried with both XPS_PMU0_INT_ID and XPS_PMU1_INT_ID, but neither worked. I tried to follow this post on using shared peripheral interrupts since PMU is this type of interrupt: https://forums.xilinx.com/t5/Processor-System-Design-and-AXI/Using-Private-and-Shared-interrupts-on-Zynq/m-p/773673
Thanks for the help,
Javier
The last parameter is incorrect. It should be 0b01 For high-level sensitivity instead of 0b10, as shown below:
XScuGic_SetPriorityTriggerType(&xInterruptController, XPS_PMU0_INT_ID, 8, 0b01); // Priority 8 (second highest) and high level sensitivity

STML4 USB virtual com port

I have the nucleo board (nucleo-L4R5ZI) and want to write a code to be able to send data from a uC to a PC via the USB. I followed some tutorials, used STM32CubeMx, other solutions found across the Internet, but anyways I failed. I can open the vcp on the PC side (using Hterm, TeraTerm and Realterm), but cannot get any data.
I use Eclipse and the buildin debugger, which I flashed to JLink.
The main loop:
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USB_DEVICE_Init();
HAL_Delay(10000);
uint8_t HiMsg[] = "0123456789987654321001234567899876543210\r\n";
while (1)
{
if( CDC_Transmit_FS(HiMsg, 20) == USBD_OK )
{
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_7); // blue LED
}
HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_14); // red LED
HAL_Delay(1000);
}
}
After executing this function, the blue LED lights only once and never changes its state (does not blink). It means that the CDC_Transmit_FS(...) returns USBD_OK only once, and next calls give USBD_Busy.
The MX_USB_DEVICE_Init() looks as follow:
void MX_USB_DEVICE_Init(void)
{
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
USBD_Start(&hUsbDeviceFS);
USBD_CDC_Init (&hUsbDeviceFS, &USBD_CDC); // I need to init it somewhere so I think here is a good place
}
The CDC_Transmit_FS looks like that:
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
uint8_t result = USBD_OK;
/* USER CODE BEGIN 7 */
CDC_Init_FS();
USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData;
if (hcdc->TxState != 0){
return USBD_BUSY;
}
USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
CDC_Init_FS();
/* USER CODE END 7 */
return result;
}
Does anyone know how to make it running? What do I miss?
Best,
This part look suspicious:
result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
CDC_Init_FS();
The call to CDC_Init_FS() probably kills the packet before it had a chance to be sent to the host.
SO... I found the solution!
I can confirm that the code above works (just remove the CDC_Init_FS)!
Acctully, it was a driver problem. for windows 10 you also need to install it despide what's written in the reference

Cannot transmit every characters through UART

I am using stm32f0 MCU.
I would like to transmit every single byte received from the uart out of the uart. I am enabling an interrupt on every byte received from uart.
My code is quite simple.
uint8_t Rx_data[5];
//Interrupt callback routine
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1) //current UART
{
HAL_UART_Transmit(&huart1, &Rx_data[0], 1, 100);
HAL_UART_Receive_IT(&huart1, Rx_data, 1); //activate UART receive interrupt every time on receiving 1 byte
}
}
My PC transmits ASCII 12345678 to stm32. If things work as expected, the PC should be receiving 12345678 back. However, the PC receives 1357 instead. What is wrong with the code?
Reenabling interrupts may be inefficient. With a couple of modifications it is possible to keep the interrupt active without needing to write the handler all over again. See the example below altered from the stm32cubemx generator.
/**
* #brief This function handles USART3 to USART6 global interrupts.
*/
void USART3_6_IRQHandler(void)
{
InterruptGPS(&huart5);
}
void InterruptGPS(UART_HandleTypeDef *huart) {
uint8_t rbyte;
if (huart->Instance != USART5) {
return;
}
/* UART in mode Receiver ---------------------------------------------------*/
if((__HAL_UART_GET_IT(huart, UART_IT_RXNE) == RESET) || (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) == RESET)) {
return;
}
rbyte = (uint8_t)(huart->Instance->RDR & (uint8_t)0xff);
__HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST);
// do your stuff
}
static void init_gps() {
__HAL_UART_ENABLE_IT(&huart5, UART_IT_RXNE);
}
You should make a tx array buffer as well, and use interrupt for writing as well (The first write if not enabled yet, should be sent immediately).
There should be examples of this for STM32 around.
You should probably switch the two lines: Transmit and Receive. The Transmit function waits for a timeout to send the character, in meantime the next received character is missed.

Communicating dsPIC with PC application through UART. Receiver interrupt handling

I'm communicating my C# applications with dsPIC x16 microcontroller using UART. I want to send/receive fixed size frames and I tried to manage it in a following way:
if(readFrame)
{ IEC0bits.U1RXIE=0; //turn off the U1RX interrupts
readFrame = false;
while(indexer < 8 )
{
while(!U1STAbits.URXDA);
modbusBuffer[indexer]=U1RXREG;
indexer++;
}
if(indexer == 8)
{
modbusRecvTask(modbusBuffer);
indexer=0;
}
IEC0bits.U1RXIE=1; //turn on U1RX interrupts
}
void _ISR_NAP _U1RXInterrupt()
{
if(IFS0bits.U1RXIF)
{
IFS0bits.U1RXIF = 0; //set the interrupt flag to false
if(U1STAbits.OERR==1) //check overload error
{
U1STAbits.OERR=0; //clear error flag
}
else
{
readFrame = true;
}
}
}
The thing is that it works fine only for the first received frame. After that the program goes into the receiver interrupt again and sets the flag readFrame to true even though no bytes were send and is getting stuck in line:
while(!U1STAbits.URXDA);
I've read some advices to clear the read buffer of the UART in order to prevent the program to go into the ISR again but I couldn't find a way to do it.