btstack/port/pic32-harmony/src/btstack_port.c
2016-04-28 14:50:33 +02:00

274 lines
7.6 KiB
C

//
// BTstack Port for the Microchip PIC32 Harmony Platfrom
//
#include "btstack_port.h"
#include "system_config.h"
#include "btstack_chipset_csr.h"
#include "btstack_debug.h"
#include "btstack_event.h"
#include "btstack_run_loop.h"
#include "btstack_run_loop_embedded.h"
#include "hci.h"
#include "hci_dump.h"
#include "hci_transport.h"
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "driver/tmr/drv_tmr.h"
#include "peripheral/usart/plib_usart.h"
#include "system/ports/sys_ports.h"
//
int btstack_main(int argc, const char * argv[]);
/// HAL Tick ///
#include "hal_tick.h"
#define APP_TMR_ALARM_PERIOD 48825
#define APP_LED_PORT PORT_CHANNEL_A
#define APP_LED_PIN PORTS_BIT_POS_4
static void dummy_handler(void);
static void (*tick_handler)(void);
static int hal_uart_needed_during_sleep = 1;
static void dummy_handler(void){};
static DRV_HANDLE handleTmr;
static bool ledIsOn;
static void sys_tick_handler ( uintptr_t context, uint32_t alarmCount ){
if (!ledIsOn) {
ledIsOn = true;
SYS_PORTS_PinSet(PORTS_ID_0, APP_LED_PORT, APP_LED_PIN);
}
else
{
ledIsOn = false;
SYS_PORTS_PinClear(PORTS_ID_0, APP_LED_PORT, APP_LED_PIN);
}
(*tick_handler)();
}
void hal_tick_init(void){
ledIsOn = false;
handleTmr = DRV_TMR_Open(APP_TMR_DRV_INDEX, DRV_IO_INTENT_EXCLUSIVE);
if( DRV_HANDLE_INVALID == handleTmr ){
log_error("Timer init failed");
return;
}
DRV_TMR_Alarm16BitRegister(handleTmr, APP_TMR_ALARM_PERIOD, true, (uintptr_t)NULL, sys_tick_handler);
DRV_TMR_Start(handleTmr);
SYS_PORTS_PinDirectionSelect(PORTS_ID_0, SYS_PORTS_DIRECTION_OUTPUT, APP_LED_PORT, APP_LED_PIN);
}
int hal_tick_get_tick_period_in_ms(void){
return 250;
}
void hal_tick_set_handler(void (*handler)(void)){
if (handler == NULL){
tick_handler = &dummy_handler;
return;
}
tick_handler = handler;
}
static void msleep(uint32_t delay) {
uint32_t wake = btstack_run_loop_embedded_get_ticks() + delay / hal_tick_get_tick_period_in_ms();
while (wake > btstack_run_loop_embedded_get_ticks()){
SYS_Tasks();
};
}
/// HAL CPU ///
#include "hal_cpu.h"
void hal_cpu_disable_irqs(void){
// TODO implement
}
void hal_cpu_enable_irqs(void){
// TODO implement
}
void hal_cpu_enable_irqs_and_sleep(void){
// TODO implement
}
/// HAL UART DMA ///
#include "hal_uart_dma.h"
// handlers
static void (*rx_done_handler)(void) = dummy_handler;
static void (*tx_done_handler)(void) = dummy_handler;
static void (*cts_irq_handler)(void) = dummy_handler;
// rx state
static uint16_t bytes_to_read = 0;
static uint8_t * rx_buffer_ptr = 0;
// tx state
static uint16_t bytes_to_write = 0;
static uint8_t * tx_buffer_ptr = 0;
// reset Bluetooth using n_shutdown
static void bluetooth_power_cycle(void){
printf("Bluetooth power cycle: Reset ON\n");
SYS_PORTS_PinClear(PORTS_ID_0, BT_RESET_PORT, BT_RESET_BIT);
msleep(250);
printf("Bluetooth power cycle: Reset OFF\n");
SYS_PORTS_PinSet(PORTS_ID_0, BT_RESET_PORT, BT_RESET_BIT);
}
void hal_uart_dma_init(void){
bytes_to_write = 0;
bytes_to_read = 0;
/* PPS Input Remapping */
PLIB_PORTS_RemapInput(PORTS_ID_0, INPUT_FUNC_U2RX, INPUT_PIN_RPF4 );
PLIB_PORTS_RemapInput(PORTS_ID_0, INPUT_FUNC_U2CTS, INPUT_PIN_RPB2 );
/* PPS Output Remapping */
PLIB_PORTS_RemapOutput(PORTS_ID_0, OUTPUT_FUNC_U2RTS, OUTPUT_PIN_RPG9 );
PLIB_PORTS_RemapOutput(PORTS_ID_0, OUTPUT_FUNC_U2TX, OUTPUT_PIN_RPF5 );
/* Initialize USART */
PLIB_USART_BaudRateSet(BT_USART_ID, SYS_CLK_PeripheralFrequencyGet(CLK_BUS_PERIPHERAL_1), BT_USART_BAUD);
PLIB_USART_HandshakeModeSelect(BT_USART_ID, USART_HANDSHAKE_MODE_FLOW_CONTROL);
PLIB_USART_OperationModeSelect(BT_USART_ID, USART_ENABLE_TX_RX_CTS_RTS_USED);
PLIB_USART_LineControlModeSelect(BT_USART_ID, USART_8N1);
// BCSP on CSR requires even parity
// PLIB_USART_LineControlModeSelect(BT_USART_ID, USART_8E1);
PLIB_USART_TransmitterEnable(BT_USART_ID);
// PLIB_USART_TransmitterInterruptModeSelect(bluetooth_uart_id, USART_TRANSMIT_FIFO_IDLE);
// allow overrun mode: not needed for H4. CSR with BCSP/H5 does not enable RTS/CTS
PLIB_USART_RunInOverflowEnable(BT_USART_ID);
PLIB_USART_ReceiverEnable(BT_USART_ID);
// PLIB_USART_ReceiverInterruptModeSelect(bluetooth_uart_id, USART_RECEIVE_FIFO_ONE_CHAR);
PLIB_USART_Enable(BT_USART_ID);
// enable _RESET
SYS_PORTS_PinDirectionSelect(PORTS_ID_0, SYS_PORTS_DIRECTION_OUTPUT, BT_RESET_PORT, BT_RESET_BIT);
bluetooth_power_cycle();
// After reset, CTS is high and we need to wait until CTS is low again
// HACK: CTS doesn't seem to work right now
msleep(250);
}
void hal_uart_dma_set_block_received( void (*the_block_handler)(void)){
rx_done_handler = the_block_handler;
}
void hal_uart_dma_set_block_sent( void (*the_block_handler)(void)){
tx_done_handler = the_block_handler;
}
void hal_uart_dma_set_csr_irq_handler( void (*the_irq_handler)(void)){
// not needed for regular H4 module (but needed for TI's eHCILL)
}
int hal_uart_dma_set_baud(uint32_t baud){
// PLIB_USART_Disable(BT_USART_ID);
// PLIB_USART_BaudRateSet(BT_USART_ID, SYS_CLK_PeripheralFrequencyGet(CLK_BUS_PERIPHERAL_1), baud);
// PLIB_USART_Enable(BT_USART_ID);
return 0;
}
void hal_uart_dma_send_block(const uint8_t *data, uint16_t size){
tx_buffer_ptr = (uint8_t *) data;
bytes_to_write = size;}
void hal_uart_dma_receive_block(uint8_t *data, uint16_t size){
// printf("hal_uart_dma_receive_block req size %u\n", size);
rx_buffer_ptr = data;
bytes_to_read = size;
}
///
static hci_transport_config_uart_t config = {
HCI_TRANSPORT_CONFIG_UART,
115200,
0, // main baudrate
1, // flow control
NULL,
};
static btstack_packet_callback_registration_t hci_event_callback_registration;
static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
if (packet_type != HCI_EVENT_PACKET) return;
if (hci_event_packet_get_type(packet) != BTSTACK_EVENT_STATE) return;
if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
printf("BTstack up and running.\n");
}
void BTSTACK_Initialize ( void )
{
printf("\n\nBTstack_Initialize()\n");
btstack_memory_init();
btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
hci_dump_open(NULL, HCI_DUMP_STDOUT);
const hci_transport_t * transport = hci_transport_h5_instance(btstack_uart_block_embedded_instance());
hci_init(transport, &config);
hci_set_chipset(btstack_chipset_csr_instance());
// inform about BTstack state
hci_event_callback_registration.callback = &packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
btstack_main(0, NULL);
}
void BTSTACK_Tasks(void){
while (bytes_to_read && PLIB_USART_ReceiverDataIsAvailable(BT_USART_ID)) {
*rx_buffer_ptr++ = PLIB_USART_ReceiverByteReceive(BT_USART_ID);
bytes_to_read--;
if (bytes_to_read == 0){
(*rx_done_handler)();
}
}
if(PLIB_USART_ReceiverOverrunHasOccurred(BT_USART_ID))
{
// printf("RX Overrun!\n");
PLIB_USART_ReceiverOverrunErrorClear(BT_USART_ID);
}
while (bytes_to_write && !PLIB_USART_TransmitterBufferIsFull(BT_USART_ID)){
PLIB_USART_TransmitterByteSend(BT_USART_ID, *tx_buffer_ptr++);
bytes_to_write--;
if (bytes_to_write == 0){
(*tx_done_handler)();
}
}
// BTstack Run Loop
btstack_run_loop_embedded_execute_once();
}