void HCI_Process(void) { uint8_t data_len; uint8_t buffer[HCI_READ_PACKET_SIZE]; tHciDataPacket * hciReadPacket = NULL; Disable_SPI_IRQ(); uint8_t list_empty = list_is_empty(&hciReadPktRxQueue); /* process any pending events read */ while(list_empty == FALSE) { list_remove_head (&hciReadPktRxQueue, (tListNode **)&hciReadPacket); Enable_SPI_IRQ(); HCI_Event_CB(hciReadPacket->dataBuff); Disable_SPI_IRQ(); list_insert_tail(&hciReadPktPool, (tListNode *)hciReadPacket); list_empty = list_is_empty(&hciReadPktRxQueue); } if (readPacketListFull) { while(BlueNRG_DataPresent()) { data_len = BlueNRG_SPI_Read_All(&SpiHandle, buffer, HCI_READ_PACKET_SIZE); if(data_len > 0) HCI_Event_CB(buffer); } readPacketListFull = FALSE; } Enable_SPI_IRQ(); }
int hci_send_req(struct hci_request *r, BOOL async) { uint8_t *ptr; uint16_t opcode = htobs(cmd_opcode_pack(r->ogf, r->ocf)); hci_event_pckt *event_pckt; hci_uart_pckt *hci_hdr; int to = DEFAULT_TIMEOUT; struct timer t; tHciDataPacket * hciReadPacket = NULL; tListNode hciTempQueue; list_init_head(&hciTempQueue); hci_send_cmd(r->ogf, r->ocf, r->clen, r->cparam); if(async){ goto done; } /* Minimum timeout is 1. */ if(to == 0) to = 1; Timer_Set(&t, to); while(1) { evt_cmd_complete *cc; evt_cmd_status *cs; evt_le_meta_event *me; int len; #if ENABLE_MICRO_SLEEP while(1){ ATOMIC_SECTION_BEGIN(); if(Timer_Expired(&t)){ ATOMIC_SECTION_END(); goto failed; } if(!HCI_Queue_Empty()){ ATOMIC_SECTION_END(); break; } Enter_Sleep_Mode(); ATOMIC_SECTION_END(); } #else while(1){ if(Timer_Expired(&t)){ goto failed; } if(!HCI_Queue_Empty()){ break; } } #endif /* Extract packet from HCI event queue. */ Disable_SPI_IRQ(); list_remove_head(&hciReadPktRxQueue, (tListNode **)&hciReadPacket); hci_hdr = (void *)hciReadPacket->dataBuff; if(hci_hdr->type != HCI_EVENT_PKT){ list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); // See comment below Enable_SPI_IRQ(); continue; } event_pckt = (void *) (hci_hdr->data); ptr = hciReadPacket->dataBuff + (1 + HCI_EVENT_HDR_SIZE); len = hciReadPacket->data_len - (1 + HCI_EVENT_HDR_SIZE); switch (event_pckt->evt) { case EVT_CMD_STATUS: cs = (void *) ptr; if (cs->opcode != opcode) goto failed; if (r->event != EVT_CMD_STATUS) { if (cs->status) { goto failed; } break; } r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_CMD_COMPLETE: cc = (void *) ptr; if (cc->opcode != opcode) goto failed; ptr += EVT_CMD_COMPLETE_SIZE; len -= EVT_CMD_COMPLETE_SIZE; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, ptr, r->rlen); goto done; case EVT_LE_META_EVENT: me = (void *) ptr; if (me->subevent != r->event) break; len -= 1; r->rlen = MIN(len, r->rlen); Osal_MemCpy(r->rparam, me->data, r->rlen); goto done; case EVT_HARDWARE_ERROR: goto failed; default: break; } /* In the meantime there could be other events from the controller. In this case, insert the packet in a different queue. These packets will be inserted back in the main queue just before exiting from send_req(). */ list_insert_tail(&hciTempQueue, (tListNode *)hciReadPacket); /* Be sure there is at list one packet in the pool to process the expected event. */ if(list_is_empty(&hciReadPktPool)){ pListNode tmp_node; list_remove_head(&hciReadPktRxQueue, &tmp_node); list_insert_tail(&hciReadPktPool, tmp_node); } Enable_SPI_IRQ(); } failed: move_list(&hciReadPktRxQueue, &hciTempQueue); Enable_SPI_IRQ(); return -1; done: // Insert the packet back into the pool. list_insert_head(&hciReadPktPool, (tListNode *)hciReadPacket); move_list(&hciReadPktRxQueue, &hciTempQueue); Enable_SPI_IRQ(); return 0; }
/******************************************************************************* * @brief Writes data from local buffer to SPI. * * @param hspi : Handle of the STM32Cube HAL SPI interface * @param data1 : First data buffer to be written * @param data2 : Second data buffer to be written * @param Nb_bytes1: Size of first data buffer to be written * @param Nb_bytes2: Size of second data buffer to be written * @retval Number of read bytes * * Called by: Hal_Write_Serial * * * _All_ those routines call this using a hardcoded pointer to &SpiHandle. * CALLERs: aci_write_hal_config -> hci_send_cmd -> hci_write -> Hal_Write_Serial() * aci_gatt_init -> hci_send_cmd -> hci_write -> Hal_Write_Serial() * aci_gap_init -> hci_send_cmd -> hci_write -> Hal_Write_Serial() *******************************************************************************/ int32_t BlueNRG_SPI_Write (SPI_HandleTypeDef *hspi, uint8_t* data1, uint8_t* data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2) { int32_t result = 0; int32_t spi_fix_enabled = 0; #ifdef ENABLE_SPI_FIX spi_fix_enabled = 1; #endif //ENABLE_SPI_FIX unsigned char header_master[HEADER_SIZE] = {0x0a, 0x00, 0x00, 0x00, 0x00}; unsigned char header_slave[HEADER_SIZE] = {0xaa, 0x00, 0x00, 0x00, 0x00}; unsigned char read_char_buf [MAX_BUFFER_SIZE]; Disable_SPI_IRQ(); /* ** If the SPI_FIX is enabled, the IRQ is set in Output mode, then it is pulled ** high and, after a delay of at least 112us, the CS line is asserted and the ** header transmit/receive operations are started. ** After these transmit/receive operations the IRQ is reset in input mode. */ if (spi_fix_enabled) { set_irq_as_output(); // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV // WVD ??? !!! CROSS_PLATFORM EXPOSURE - esp for FASTER DEVICES !!! ??? // VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV /* Wait to Assert CS line until after at least 112us */ us150Delay(); } /* ASSERT CS line */ ////HAL_GPIO_WritePin (BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_RESET); ASSERT_CS_BlueNRG(); // Ensure CS is set to ACTIVE /* Exchange header with BlueNRG */ ////HAL_SPI_TransmitReceive (hspi, header_master, header_slave, HEADER_SIZE, TIMEOUT_DURATION); // WORKS spi_Write_Read (BLE_BLUENRG_SPI_ID, header_master, header_slave, HEADER_SIZE, 0); if (spi_fix_enabled) { set_irq_as_input(); } if (header_slave[0] == 0x02) { /* SPI is ready */ if (header_slave[1] >= (Nb_bytes1+Nb_bytes2)) { /* ensure Buffer is big enough */ if (Nb_bytes1 > 0) { //// HAL_SPI_TransmitReceive (hspi, data1, read_char_buf, Nb_bytes1, TIMEOUT_DURATION); spi_Write_Read (BLE_BLUENRG_SPI_ID, data1, read_char_buf, Nb_bytes1, 0); } if (Nb_bytes2 > 0) { //// HAL_SPI_TransmitReceive (hspi, data2, read_char_buf, Nb_bytes2, TIMEOUT_DURATION); spi_Write_Read (BLE_BLUENRG_SPI_ID, data2, read_char_buf, Nb_bytes2, 0); } } else { /* Buffer is too small */ result = -2; } } else { /* SPI is not ready */ result = -1; } /* Release CS line */ ////HAL_GPIO_WritePin (BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); DEASSERT_CS_BlueNRG(); // Ensure CS is set to NOT active Enable_SPI_IRQ(); return result; }
/** * @brief Writes data from local buffer to SPI. * @param hspi : Handle of the STM32Cube HAL SPI interface * @param data1 : First data buffer to be written * @param data2 : Second data buffer to be written * @param Nb_bytes1: Size of first data buffer to be written * @param Nb_bytes2: Size of second data buffer to be written * @retval Number of read bytes */ int32_t BlueNRG_SPI_Write(SPI_HandleTypeDef * hspi, uint8_t * data1, uint8_t * data2, uint8_t Nb_bytes1, uint8_t Nb_bytes2) { int32_t result = 0; int32_t spi_fix_enabled = 0; #ifdef ENABLE_SPI_FIX spi_fix_enabled = 1; #endif //ENABLE_SPI_FIX unsigned char header_master[HEADER_SIZE] = { 0x0a, 0x00, 0x00, 0x00, 0x00 }; unsigned char header_slave[HEADER_SIZE] = { 0xaa, 0x00, 0x00, 0x00, 0x00 }; unsigned char read_char_buf[MAX_BUFFER_SIZE]; Disable_SPI_IRQ(); /* If the SPI_FIX is enabled the IRQ is set in Output mode, then it is pulled high and, after a delay of at least 112us, the CS line is asserted and the header transmit/receive operations are started. After these transmit/receive operations the IRQ is reset in input mode. */ if (spi_fix_enabled) { set_irq_as_output(); /* Assert CS line after at least 112us */ us150Delay(); } /* CS reset */ HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_RESET); /* Exchange header */ HAL_SPI_TransmitReceive(hspi, header_master, header_slave, HEADER_SIZE, TIMEOUT_DURATION); if (spi_fix_enabled) { set_irq_as_input(); } if (header_slave[0] == 0x02) { /* SPI is ready */ if (header_slave[1] >= (Nb_bytes1 + Nb_bytes2)) { /* Buffer is big enough */ if (Nb_bytes1 > 0) { HAL_SPI_TransmitReceive(hspi, data1, read_char_buf, Nb_bytes1, TIMEOUT_DURATION); } if (Nb_bytes2 > 0) { HAL_SPI_TransmitReceive(hspi, data2, read_char_buf, Nb_bytes2, TIMEOUT_DURATION); } } else { /* Buffer is too small */ result = -2; } } else { /* SPI is not ready */ result = -1; } /* Release CS line */ HAL_GPIO_WritePin(BNRG_SPI_CS_PORT, BNRG_SPI_CS_PIN, GPIO_PIN_SET); Enable_SPI_IRQ(); return result; }
void new_hci_event(void *pckt, uint16_t len) { Disable_SPI_IRQ(); /* Must be re-enabled after packet processing. */ new_packet = TRUE; }