bouffalolab / bouffalo_sdk

BouffaloSDK is the IOT and MCU software development kit provided by the Bouffalo Lab Team, supports all the series of Bouffalo chips. Also it is the combination of bl_mcu_sdk and bl_iot_sdk
Apache License 2.0
372 stars 127 forks source link

BL616 keyboard hid #134

Closed beckmx closed 1 year ago

beckmx commented 1 year ago

Hello again guys, I am trying to run a bl616 as a usb hid keyboard, I noticed the example from the cherryusb repo, I imported the c-file in my project and looks like it compiled , the problem i see is that, neither the shell work nor the usb keyboard functionality, looks like it got stuck somewhere

#include "shell.h"
#include <FreeRTOS.h>
#include "task.h"
#include "board.h"
#include "usbh_core.h"
#include "usbd_core.h"
#include "bflb_mtimer.h"
#include <string.h>
//#include "hid_keyboard_template.c"

extern void hid_keyboard_init(void);
extern void hid_keyboard_test(void);
static struct bflb_device_s *uart0;
extern void shell_init_with_task(struct bflb_device_s *shell);
int main(void)
{
    board_init();

    uart0 = bflb_device_get_by_name("uart0");
    shell_init_with_task(uart0);
    printf("CherryUSB device example");
    hid_keyboard_init();

    while (!usb_device_is_configured()) {}
    printf("Keyboard started succesfully!");
   while (1) {
    hid_keyboard_test();    
    bflb_mtimer_delay_ms(2000);
  }
  return 0;
}
sakumisu commented 1 year ago

Do you really use freertos?I think you need to study freertos first, thanks.

sakumisu commented 1 year ago

Or disable freertos.

beckmx commented 1 year ago

I dont use freertos, but I noticed other examples used it for the shell (I guess?) if I deactivate the freertos from here:

set(CONFIG_BFLOG 0)
set(CONFIG_FREERTOS 0)
set(CONFIG_SHELL 1)
set(CONFIG_CHERRYUSB 1)
set(CONFIG_CHERRYUSB_DEVICE 1)
set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
set(CONFIG_CHERRYUSB_DEVICE_HID 1)
set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
set(CONFIG_CHERRYUSB_DEVICE_AUDIO 1)
set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1)

It throws an error:

main.c:19: undefined reference toshell_init_with_task'`

I also tried only commenting the freertos includes with the config_freertos active but still the usb didnt work, also nothing displays on shell

#include "shell.h"
//#include <FreeRTOS.h>
//#include "task.h"
#include "board.h"
#include "usbh_core.h"
#include "usbd_core.h"
#include "bflb_mtimer.h"
#include <string.h>
//#include "hid_keyboard_template.c"

extern void hid_keyboard_init(void);
extern void hid_keyboard_test(void);
static struct bflb_device_s *uart0;
extern void shell_init_with_task(struct bflb_device_s *shell);
int main(void)
{
    board_init();

    uart0 = bflb_device_get_by_name("uart0");
    shell_init_with_task(uart0);
    printf("CherryUSB device example");
    hid_keyboard_init();

    while (!usb_device_is_configured()) {}
    printf("Keyboard started succesfully!");
   while (1) {
    hid_keyboard_test();    
    bflb_mtimer_delay_ms(2000);
  }
  return 0;
}
sakumisu commented 1 year ago

Why dont you go to the shell_init_with_task to see its implement?

sakumisu commented 1 year ago

Refer to https://github.com/bouffalolab/bouffalo_sdk/tree/master/examples/shell

sakumisu commented 1 year ago

So i think it is your yourself problem, shell_init_with_task must use freertos.

beckmx commented 1 year ago

Let me try that

beckmx commented 1 year ago

@sakumisu it works :)

Screenshot 2023-04-24 at 22 48 55

If i have doubts, I will let u know, thanx!

beckmx commented 1 year ago

Hello @sakumisu I know I have a problem with the code, I am just not able to properly figure the issue out, if you can approach me into the right direction I can continue with the next steps I have read the docs about the HID keyboard but I have some doubts, these are the steps I have taken so far:

Problem: Sending 1 single key makes the BL616 somehow send several key presses, for instance the example from hid_keyboard_template is suppose to send "A" but initially it was sending "m" from my image above, I switched the way the methods are called (just a switch in order) and it sends several key presses but I don't understand why exactly that happens this is the code on my main.c

#include "shell.h"
#include "board.h"
#include "usbh_core.h"
#include "usbd_core.h"
#include "bflb_mtimer.h"
#include <string.h>
#include "bflb_uart.h"
//#include "hid_keyboard_template.c"

extern void hid_keyboard_init(void);
extern void hid_keyboard_test(void);
static struct bflb_device_s *uart0;

void uart_isr(int irq, void *arg)
{
    uint32_t intstatus = bflb_uart_get_intstatus(uart0);
    if (intstatus & UART_INTSTS_RX_FIFO) {
        while (bflb_uart_rxavailable(uart0)) {
            shell_handler(bflb_uart_getchar(uart0));
        }
    }
    if (intstatus & UART_INTSTS_RTO) {
        while (bflb_uart_rxavailable(uart0)) {
            shell_handler(bflb_uart_getchar(uart0));
        }
        bflb_uart_int_clear(uart0, UART_INTCLR_RTO);
    }
}

int main(void)
{
    int ch;
    board_init();
    uart0 = bflb_device_get_by_name("uart0");
    bflb_uart_rxint_mask(uart0, false);
    bflb_irq_attach(uart0->irq_num, uart_isr, uart0);
    bflb_irq_enable(uart0->irq_num);

    printf("CherryUSB device example");
    hid_keyboard_init();

    usb_device_is_configured();
    bflb_mtimer_delay_ms(2000);
    printf("Keyboard started succesfully!");
    shell_init();
    while (1) {
        // if((ch = bflb_uart_getchar(uart0)) != -1)
        // {
        //     shell_handler(ch);
        // }
    hid_keyboard_test();
    uint8_t sendbuffer[8] = {0};
    usbd_ep_start_write(0x81, sendbuffer, 8);
    bflb_mtimer_delay_ms(5000);
    }
  return 0;
}

The method from hid_keyboard_templace.c is this:

void hid_keyboard_test(void)
{
    uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A

    int ret = usbd_ep_start_write(HID_INT_EP, sendbuffer, 8);
    if (ret < 0) {
        return;
    }
    hid_state = HID_STATE_BUSY;
    while (hid_state == HID_STATE_BUSY) {
    }
}

My proj.conf looks like this:

set(CONFIG_BFLOG 0)
set(CONFIG_SHELL 1)
set(CONFIG_CHERRYUSB 1)
set(CONFIG_CHERRYUSB_DEVICE 1)
set(CONFIG_CHERRYUSB_DEVICE_CDC 1)
set(CONFIG_CHERRYUSB_DEVICE_HID 1)
set(CONFIG_CHERRYUSB_DEVICE_MSC 1)
set(CONFIG_CHERRYUSB_DEVICE_AUDIO 1)
set(CONFIG_CHERRYUSB_DEVICE_VIDEO 1)

it generates, several keypresses as shown in this image and keeps pressing those keys constantly

Screenshot 2023-05-03 at 13 24 19
sakumisu commented 1 year ago

usbd_ep_start_write is aync api, please correct your demo.

sakumisu commented 1 year ago

usb_device_is_configured() is check api , please correct. when usb is not configured, no access to use usbd_ep_start_write.

sakumisu commented 1 year ago

You can use the origin template for test.

beckmx commented 1 year ago

Ok, let me dig in again, actually yes I noticed the usb_device_is_configured() is always false that’s why I removed the while that verifies that. Let me check again the code with your hints

beckmx commented 1 year ago

Hello again, I changed the project to call the keystroke via async using freertos but still I am getting different keystrokes that are not the letter "A", I used this code:

#include "shell.h"
#include <FreeRTOS.h>
#include "task.h"
#include "board.h"

#include "bflb_mtimer.h"
#include "bflb_uart.h"
#include "usbh_core.h"
#include "usbd_core.h"
#include <string.h>
#include "bl616_glb.h"
#include "cJSON/cJSON.h"
#include "hid_keyboard_template.c"

extern void hid_keyboard_init(void);
extern void hid_keyboard_test(void);
static struct bflb_device_s *uart0;

extern void shell_init_with_task(struct bflb_device_s *shell);

void sendSingleKey(void *pvParameters) {
    const TickType_t xDelay = 5000 / portTICK_PERIOD_MS; // 5000 ms (5 seconds) delay
 while (1) {
    if (hid_state == HID_STATE_BUSY) {
        // Your code to handle the busy state
        // ...
    } else {
        hid_keyboard_test();
    }
    vTaskDelay(xDelay);
  }
}
int main(void)
{
    board_init();
    configASSERT((configMAX_PRIORITIES > 4));

    uart0 = bflb_device_get_by_name("uart0");
    shell_init_with_task(uart0);

    printf("CherryUSB device example");
    hid_keyboard_init();

    printf("Keyboard started succesfully!");
    // create a freertos task to repeat every 5 seconds
    xTaskCreate(sendSingleKey, "send_single_key", 1024, NULL, 1, NULL);
    vTaskStartScheduler();

   while (1)
   {
    /* code */
   }

  return 0;
}

I dont see any issues on the console from the uart, so I assumed it is running well

Screenshot 2023-05-04 at 11 39 29

I removed the while in the test method:

void hid_keyboard_test(void)
{
    uint8_t sendbuffer[8] = { 0x00, 0x00, HID_KBD_USAGE_A, 0x00, 0x00, 0x00, 0x00, 0x00 }; //A

    int ret = usbd_ep_start_write(HID_INT_EP, sendbuffer, 8);
    if (ret < 0) {
        return;
    }
    hid_state = HID_STATE_BUSY;
}

I am still getting several keystrokes at once:


  {
    "type": "down",
    "name": {"key_code":"tab"},
    "usagePage": "7 (0x0007)",
    "usage": "43 (0x002b)",
    "misc": ""
  },
  {
    "type": "down",
    "name": {"key_code":"keypad_0"},
    "usagePage": "7 (0x0007)",
    "usage": "98 (0x0062)",
    "misc": ""
  },
  {
    "type": "down",
    "name": {"key_code":"f14"},
    "usagePage": "7 (0x0007)",
    "usage": "105 (0x0069)",
    "misc": ""
  },
  {
    "type": "down",
    "name": {"key_code":"keypad_3"},
    "usagePage": "7 (0x0007)",
    "usage": "91 (0x005b)",
    "misc": ""
  },
  {
    "type": "down",
    "name": {"key_code":"right_command"},
    "usagePage": "7 (0x0007)",
    "usage": "231 (0x00e7)",
    "misc": "flags right_command"
  },
  {
    "type": "down",
    "name": {"key_code":"right_option"},
    "usagePage": "7 (0x0007)",
    "usage": "230 (0x00e6)",
    "misc": "flags right_command,right_option"
  },
  {
    "type": "down",
    "name": {"key_code":"right_control"},
    "usagePage": "7 (0x0007)",
    "usage": "228 (0x00e4)",
    "misc": "flags right_command,right_control,right_option"
  },
  {
    "type": "down",
    "name": {"key_code":"left_command"},
    "usagePage": "7 (0x0007)",
    "usage": "227 (0x00e3)",
    "misc": "flags left_command,right_command,right_control,right_option"
  },
  {
    "type": "down",
    "name": {"key_code":"left_option"},
    "usagePage": "7 (0x0007)",
    "usage": "226 (0x00e2)",
    "misc": "flags left_command,left_option,right_command,right_control,right_option"
  },
  {
    "type": "down",
    "name": {"key_code":"left_control"},
    "usagePage": "7 (0x0007)",
    "usage": "224 (0x00e0)",
    "misc": "flags left_command,left_control,left_option,right_command,right_control,right_option"
  },
beckmx commented 1 year ago

@sakumisu if you can point me to an example for the bl616 where it uses the async methods I can study those, thanx!

sakumisu commented 1 year ago

Why do you remove the while? Do you know usbd_ep_start_write is the async api??

sakumisu commented 1 year ago

Do you know what is async ?

sakumisu commented 1 year ago

I saw the usb hid works, so i think the left work is to study hid keyboard descriptor.

sakumisu commented 1 year ago

And why output m not A, because bl616 has cache, sendbuffer must be in nocache ram or clean cache.

sakumisu commented 1 year ago

Refer to https://github.com/bouffalolab/bouffalo_sdk/tree/master/examples/peripherals/usbdev/usbd_hid_keyboard

beckmx commented 1 year ago

@sakumisu thank you very much, looks like this line:

bflb_l1c_dcache_clean_range(sendbuffer, 8);

Made the whole difference, it does behave totally different when including that, does it mean that for variables inside methods I should clean them from the L1 cache?, or what can be a good point of reference to know if I need to clean the cache, and the "nocache" would be like this?:

ATTR_NOCACHE_NOINIT_RAM_SECTION uint8_t sendbuffer[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

Thanx a lot for your wisdom

sakumisu commented 1 year ago

ATTR_NOCACHE_NOINIT_RAM_SECTION does not init sendbuffer.

sakumisu commented 1 year ago

You can search for cache in google to study.

sakumisu commented 1 year ago

I think this issue is done.