| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391 |
- #ifndef APPLICATIONS_HCI_INTERFACE_C_
- #define APPLICATIONS_HCI_INTERFACE_C_
- #include <rtthread.h>
- #include <rtdevice.h>
- #include "rtthread_driver_spi.h"
- #include "drivers/hci_driver.h"
- #include "drivers/hci_h4.h"
- #include "logging/bt_log_impl.h"
- #include "common/bt_buf.h"
- struct hci_trans_spi_config {
- const char *device_name; /* spi device name, i.e. "spi1" */
- const char *bus_name; /* spi BUS name, i.e. "spi10" */
- int cs_pin_num; /* RT-Thread drv_gpio number of SPI CS PIN */
- int irq_pin_num; /* RT-Thread drv_gpio number of SPI IRQ PIN */
- uint32_t rate;
- int data_width; /* Data width: 8bits, 16bits, 32bits */
- int LSB_MSB; /* Data transmission order: LSB:0 MSB:1 */
- int Master_Slave; /* Set the master-slave mode of SPI: Master:0 Slave:1 */
- int CPOL; /* Set clock polarity(CPOL): 0 1 */
- int CPHA; /* Set clock phase(CPHA): 0 1 */
- };
- static struct hci_trans_spi_config hci_config;
- struct rt_spi_device *ble_spi = RT_NULL;
- int32_t IsDataAvailable(void);
- void hci_driver_init_loop(void);
- int32_t HCI_TL_SPI_Init(void* pConf)
- {
- /******PIN******/
- rt_pin_mode(hci_config.irq_pin_num, PIN_MODE_INPUT); // IRQ input
- rt_pin_mode(hci_config.cs_pin_num, PIN_MODE_OUTPUT); // CS output
- /*******SPI******/
- RT_ASSERT(hci_config.device_name);
- RT_ASSERT(hci_config.bus_name);
- ble_spi = (struct rt_spi_device *)rt_malloc(sizeof(struct rt_spi_device));
- if(RT_NULL == ble_spi)
- {
- printk("Failed to malloc the spi device.\n");
- return -RT_ENOMEM;
- }
- if (RT_EOK != rt_spi_bus_attach_device(ble_spi, hci_config.device_name, hci_config.bus_name, RT_NULL))
- {
- printk("Failed to attach the spi device.\n");
- return -RT_ERROR;
- }
- /*******SPI Device Config*******/
- struct rt_spi_configuration cfg;
- cfg.data_width = hci_config.data_width;
- cfg.mode = (hci_config.Master_Slave << 3) |
- ((hci_config.CPOL << 1) | (hci_config.CPHA << 0)) |
- (hci_config.LSB_MSB << 2);
- cfg.max_hz = hci_config.rate; /* 1M */
- if (RT_EOK != rt_spi_configure(ble_spi, &cfg)) {
- printk("Failed to config the spi device.\n");
- return -RT_ERROR;
- }
- return RT_EOK;
- }
- /**
- * @brief Reads from BlueNRG SPI buffer and store data into local buffer.
- *
- * @param buffer : Buffer where data from SPI are stored
- * @param size : Buffer size
- * @retval int32_t: Number of read bytes
- */
- int32_t HCI_TL_SPI_Receive(uint8_t* buffer, uint16_t size)
- {
- uint16_t byte_count;
- uint8_t len = 0;
- uint8_t char_00 = 0x00;
- volatile uint8_t read_char;
- uint8_t header_master[HEADER_SIZE] = {0x0b, 0x00, 0x00, 0x00, 0x00};
- uint8_t header_slave[HEADER_SIZE];
- uint32_t tickstart_data_available = rt_tick_get();
- /* CS reset */
- rt_pin_write(hci_config.cs_pin_num, PIN_LOW);
- /*check transfer Available*/
- while(!IsDataAvailable())
- {
- if((rt_tick_get() - tickstart_data_available) > TIMEOUT_DURATION)
- {
- printk(" SPI Recv timeout : %d\r\n", rt_tick_get() - tickstart_data_available);
- return -3;
- }
- }
- /* Read the header */
- rt_spi_transfer(ble_spi, &header_master, &header_slave, HEADER_SIZE); //RTAPI
- /* device is ready */
- byte_count = (header_slave[4] << 8)| header_slave[3];
- if(byte_count > 0)
- {
- /* avoid to read more data than the size of the buffer */
- if (byte_count > size)
- {
- byte_count = size;
- }
- for(len = 0; len < byte_count; len++)
- {
- rt_spi_transfer(ble_spi, &char_00, (uint8_t*)&read_char, 1);
- buffer[len] = read_char;
- }
- }
- /**
- * To be aligned to the SPI protocol.
- * Can bring to a delay inside the frame, due to the BlueNRG-2 that needs
- * to check if the header is received or not.
- */
- uint32_t tickstart = rt_tick_get();
- while ((rt_tick_get() - tickstart) < TIMEOUT_IRQ_HIGH) {
- if (rt_pin_read(hci_config.irq_pin_num) == PIN_LOW) {
- break;
- }
- }
- /* Release CS line */
- rt_pin_write(hci_config.cs_pin_num, PIN_HIGH);
- tickstart = rt_tick_get();
- while ((rt_tick_get() - tickstart) < TIMEOUT_HIGH) {
- if (rt_pin_read(hci_config.irq_pin_num) == PIN_HIGH) {
- break;
- }
- }
- return len;
- }
- /**
- * @brief Writes data from local buffer to SPI.
- *
- * @param buffer : data buffer to be written
- * @param size : size of first data buffer to be written
- * @retval int32_t: Number of read bytes
- */
- int32_t HCI_TL_SPI_Send(uint8_t* buffer, uint16_t size)
- {
- int32_t result;
- uint16_t rx_bytes;
- uint8_t char_00 = 0x00;
- volatile uint8_t read_char;
- uint8_t header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00};
- uint8_t header_slave[HEADER_SIZE];
- static uint8_t read_char_buf[MAX_BUFFER_SIZE];
- uint32_t tickstart = rt_tick_get();
- do
- {
- uint32_t tickstart_data_available = rt_tick_get();
- result = 0;
- /* CS reset */
- rt_pin_write(hci_config.cs_pin_num, PIN_LOW);
- /*
- * Wait until BlueNRG-2 is ready.
- * When ready it will raise the IRQ pin.
- */
- while(!IsDataAvailable())
- {
- if((rt_tick_get() - tickstart_data_available) > TIMEOUT_DURATION)
- {
- printk("SPI Send timeout %d\r\n", rt_tick_get() - tickstart_data_available);
- result = -3;
- break;
- }
- }
- if(result == -3)
- {
- /* The break causes the exiting from the "while", so the CS line must be released */
- rt_pin_write(hci_config.cs_pin_num, PIN_HIGH);
- break;
- }
- /* Read header */
- rt_spi_transfer(ble_spi, &header_master, &header_slave, HEADER_SIZE);
- rx_bytes = (((uint16_t)header_slave[2])<<8) | ((uint16_t)header_slave[1]);
- uint16_t byte_count = (header_slave[4] << 8)| header_slave[3];
- if (byte_count > 0)
- {
- /* Release CS line */
- rt_pin_write(hci_config.cs_pin_num, PIN_HIGH);
- /* to end the send, we need a delay */
- rt_thread_delay(1);
- hci_driver_init_loop();
- result = -2;
- }
- else
- {
- if(rx_bytes >= size)
- {
- /* Buffer is big enough */
- rt_spi_transfer(ble_spi, buffer, &read_char_buf, size);
- }
- else
- {
- /* Buffer is too small */
- result = -2;
- }
- /* Release CS line */
- rt_pin_write(hci_config.cs_pin_num, PIN_HIGH);
- }
- } while(result < 0);
- /**
- * To be aligned to the SPI protocol.
- * Can bring to a delay inside the frame, due to the BlueNRG-2 that needs
- * to check if the header is received or not.
- */
- tickstart = rt_tick_get();
- while ((rt_tick_get() - tickstart) < TIMEOUT_IRQ_HIGH) {
- if (rt_pin_read(hci_config.irq_pin_num) == PIN_LOW) {
- break;
- }
- }
- return result;
- }
- /**
- * @brief Reports if the BlueNRG has data for the host micro.
- *
- * @param None
- * @retval int32_t: 1 if data are present, 0 otherwise
- */
- int32_t IsDataAvailable(void)
- {
- return (rt_pin_read(hci_config.irq_pin_num) == PIN_HIGH);
- }
- static int hci_driver_open(void)
- {
- HCI_TL_SPI_Init(NULL); // RT SPI init
- printk("hci_driver_open, SPI_config_finish\n");
- return 0;
- }
- int switch_net_buf_type(uint8_t type)
- {
- switch (type)
- {
- case BT_BUF_ACL_OUT:
- return HCI_ACLDATA_PKT;
- case BT_BUF_CMD:
- return HCI_COMMAND_PKT;
- default:
- printk("Unknown buffer type");
- }
- return 0;
- }
- static int hci_driver_send(struct net_buf *buf)
- {
- uint8_t type = bt_buf_get_type(buf);
- // net_buf_push_u8(buf, type);
- // uint8_t* data = buf->data;
- uint8_t len = buf->len;
- if(len >= MAX_BUFFER_SIZE)
- {
- return -1;
- }
- uint8_t data[MAX_BUFFER_SIZE];
- data[0] = switch_net_buf_type(type);
- memcpy(data + 1, buf->data, len); //data[0] is the type copy to data[1]
- // printk("hci_driver_send, type: %d, len: %d, data: %02x:%02x:%02x:%02x:%02x:%02x\n", type, len, data[0], data[1], data[2], data[3], data[4], data[5]);
- if (HCI_TL_SPI_Send(data, len + 1) < 0) { // type +1
- return -1;
- }
- net_buf_unref(buf);
- return 0;
- }
- static int hci_driver_recv(uint8_t *buf, uint16_t len)
- {
- return HCI_TL_SPI_Receive(buf, len);
- }
- void hci_driver_init_loop(void)
- {
- uint8_t data[MAX_BUFFER_SIZE];
- uint8_t len = MAX_BUFFER_SIZE;
- int ret = HCI_TL_SPI_Receive(data, len); //ret: bytes num Recv
- if(ret > 0 && (data[0] != 0)) // type cant be 0
- {
- // printk("hci_driver_init_loop, ret: %d, data: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
- // ret, data[0], data[1], data[2], data[3], data[4], data[5],data[6],data[7]);
- struct net_buf *buf;
- switch(data[0])
- {
- case HCI_EVENT_PKT:
- buf = bt_buf_get_controller_tx_evt();
- break;
- case HCI_ACLDATA_PKT:
- buf = bt_buf_get_controller_tx_acl();
- break;
- default:
- return;
- }
- if (buf)
- {
- net_buf_add_mem(buf, data + 1, ret - 1);
- bt_recv(buf);
- }
- }
- }
- static const struct bt_hci_driver drv = {
- .open = hci_driver_open,
- .send = hci_driver_send,
- };
- static char device_name[NAME_SIZE];
- static char bus_name[NAME_SIZE];
- int hci_driver_init(bt_BlueNRG_SPI_interface_t *hci_cfg, int device_idx, int spi_index)
- {
- rt_sprintf(bus_name, "spi%d", spi_index);
- hci_config.bus_name = bus_name;
- rt_sprintf(device_name, "spi%d%d", spi_index, device_idx);
- hci_config.device_name = device_name;
- hci_config.rate = hci_cfg->rate;
- hci_config.data_width = hci_cfg->data_width;
- hci_config.LSB_MSB = hci_cfg->LSB_MSB;
- hci_config.Master_Slave = hci_cfg->Master_Slave;
- hci_config.CPOL = hci_cfg->CPOL;
- hci_config.CPHA = hci_cfg->CPHA;
- hci_config.cs_pin_num = hci_cfg->cs_pin_num;
- hci_config.irq_pin_num = hci_cfg->irq_pin_num;
- printk("SPI_init_process device_name: %s, spi_name: %s, rate: %d, databits: %d, LSB_MSB: %d, Master_Slave: %d, CPOL: %d, CPHA: %d\n",
- hci_config.device_name, hci_config.bus_name, hci_config.rate, hci_config.data_width,
- hci_config.LSB_MSB, hci_config.Master_Slave, hci_config.CPOL, hci_config.CPHA);
- printk("SPI_init_process cs_pin_num: %d, irq_pin_num: %d\n",
- hci_config.cs_pin_num, hci_config.irq_pin_num);
- if (bt_hci_driver_register(&drv) != 0)
- {
- return -1;
- }
- return 0;
- }
- #endif /* APPLICATIONS_HCI_INTERFACE_C_ */
|