btstack/port/stm32-l053r8-em9304/port.c
2017-07-04 21:13:38 +02:00

411 lines
11 KiB
C

#include <string.h>
#include "stm32l0xx_hal.h"
#include "port.h"
#include "main.h" // pin definitions
// retarget printf
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
int _write(int file, char *ptr, int len){
uint8_t cr = '\r';
if (file == STDOUT_FILENO || file == STDERR_FILENO) {
int i;
for (i = 0; i < len; i++) {
if (ptr[i] == '\n') {
HAL_UART_Transmit( &huart2, &cr, 1, HAL_MAX_DELAY );
}
HAL_UART_Transmit( &huart2, (uint8_t *) &ptr[i], 1, HAL_MAX_DELAY );
}
return i;
}
errno = EIO;
return -1;
}
int _read(int file, char * ptr, int len){
(void)(file);
(void)(ptr);
(void)(len);
return -1;
}
int _close(int file){
(void)(file);
return -1;
}
int _isatty(int file){
(void)(file);
return -1;
}
int _lseek(int file){
(void)(file);
return -1;
}
int _fstat(int file){
(void)(file);
return -1;
}
// EM 9304 SPI Master HCI Implementation
#define STS_SLAVE_READY 0xc0
// SPI Write Command
static const uint8_t hal_spi_em9304_write_command[] = {
0x42,
0x00,
};
// SPI Read Command
static const uint8_t hal_spi_em9304_read_command[] = {
0x81,
0x00,
};
const uint8_t hci_reset[] = { 0x01, 0x03, 0x0c, 0x00 };
static volatile enum {
SPI_EM9304_IDLE,
SPI_EM9304_RX_W4_READ_COMMAND_SENT,
SPI_EM9304_RX_READ_COMMAND_SENT,
SPI_EM9304_RX_W4_DATA_RECEIVED,
SPI_EM9304_RX_DATA_RECEIVED,
SPI_EM9304_TX_W4_RDY,
SPI_EM9304_TX_W4_WRITE_COMMAND_SENT,
SPI_EM9304_TX_WRITE_COMMAND_SENT,
SPI_EM9304_TX_W4_DATA_SENT,
SPI_EM9304_TX_DATA_SENT,
} hal_spi_em9304_state;
#define SPI_EM9304_RX_BUFFER_SIZE 64
static uint8_t hal_spi_em9304_slave_status[2];
static uint8_t hal_spi_em9304_rx_buffer[SPI_EM9304_RX_BUFFER_SIZE];
static uint16_t hal_spi_em9304_rx_pos;
static const uint8_t * hal_uart_dma_tx_data;
static uint16_t hal_uart_dma_tx_size;
static uint8_t * hal_uart_dma_rx_buffer;
static uint16_t hal_uart_dma_rx_len;
static void dummy_handler(void);
// handlers
static void (*rx_done_handler)(void) = &dummy_handler;
static void (*tx_done_handler)(void) = &dummy_handler;
// test
static int test_done;
static volatile int run_loop_triggered;
static inline void hal_spi_em9304_trigger_run_loop(void){
run_loop_triggered = 1;
}
static inline int hal_spi_em9304_rdy(void){
return HAL_GPIO_ReadPin(SPI1_RDY_GPIO_Port, SPI1_RDY_Pin) == GPIO_PIN_SET;
}
static inline uint16_t hal_spi_em9304_rx_free_bytes(void){
return SPI_EM9304_RX_BUFFER_SIZE - hal_spi_em9304_rx_pos;
}
static void hal_spi_em9304_reset(void){
hal_spi_em9304_rx_pos = 0;
}
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi){
switch (hal_spi_em9304_state){
case SPI_EM9304_RX_W4_READ_COMMAND_SENT:
hal_spi_em9304_state = SPI_EM9304_RX_READ_COMMAND_SENT;
hal_spi_em9304_trigger_run_loop();
break;
case SPI_EM9304_TX_W4_WRITE_COMMAND_SENT:
hal_spi_em9304_state = SPI_EM9304_TX_WRITE_COMMAND_SENT;
hal_spi_em9304_trigger_run_loop();
break;
default:
break;
}
}
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi){
switch (hal_spi_em9304_state){
case SPI_EM9304_RX_W4_DATA_RECEIVED:
hal_spi_em9304_state = SPI_EM9304_RX_DATA_RECEIVED;
hal_spi_em9304_trigger_run_loop();
break;
default:
break;
}
}
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi){
switch (hal_spi_em9304_state){
case SPI_EM9304_TX_W4_DATA_SENT:
hal_spi_em9304_state = SPI_EM9304_TX_DATA_SENT;
hal_spi_em9304_trigger_run_loop();
break;
default:
break;
}
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){
if (hal_spi_em9304_rdy()){
hal_spi_em9304_trigger_run_loop();
}
}
static void hal_spi_em9304_transfer_rx_data(void){
// log_info("hal_spi_em9304_transfer_rx_data: rx buffer %u -> hci buffer %u\n", hal_spi_em9304_rx_pos, hal_uart_dma_rx_len);
while (hal_spi_em9304_rx_pos && hal_uart_dma_rx_len){
uint16_t bytes_to_copy = hal_uart_dma_rx_len;
if (hal_uart_dma_rx_len > hal_spi_em9304_rx_pos){
bytes_to_copy = hal_spi_em9304_rx_pos;
}
memcpy(hal_uart_dma_rx_buffer, hal_spi_em9304_rx_buffer, bytes_to_copy);
hal_uart_dma_rx_buffer += bytes_to_copy;
hal_uart_dma_rx_len -= bytes_to_copy;
hal_spi_em9304_rx_pos -= bytes_to_copy;
// shift rest of data - could be skipped if ring buffer is used
if (hal_spi_em9304_rx_pos){
// log_info("move %u bytes down\n", hal_spi_em9304_rx_pos);
memmove(hal_spi_em9304_rx_buffer, &hal_spi_em9304_rx_buffer[bytes_to_copy], hal_spi_em9304_rx_pos);
}
if (hal_uart_dma_rx_len == 0){
(*rx_done_handler)();
}
}
}
static void hal_spi_em9304_process(void){
uint16_t bytes_to_read;
uint16_t bytes_ready;
uint16_t max_bytes_to_send;
uint16_t bytes_to_send;
switch (hal_spi_em9304_state){
case SPI_EM9304_IDLE:
// RDY && space in RX Buffer
if (hal_spi_em9304_rdy() && hal_spi_em9304_rx_free_bytes()){
// chip select
HAL_GPIO_WritePin(SPI1_CSN_GPIO_Port, SPI1_CSN_Pin, GPIO_PIN_RESET);
// wait for read command sent
hal_spi_em9304_state = SPI_EM9304_RX_W4_READ_COMMAND_SENT;
// send read command
HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t*) hal_spi_em9304_read_command, hal_spi_em9304_slave_status, sizeof(hal_spi_em9304_read_command));
}
if (hal_uart_dma_tx_size){
// chip select
HAL_GPIO_WritePin(SPI1_CSN_GPIO_Port, SPI1_CSN_Pin, GPIO_PIN_RESET);
// wait for RDY
hal_spi_em9304_state = SPI_EM9304_TX_W4_RDY;
}
break;
case SPI_EM9304_RX_READ_COMMAND_SENT:
bytes_ready = hal_spi_em9304_slave_status[1];
bytes_to_read = bytes_ready;
if (bytes_to_read > hal_spi_em9304_rx_free_bytes()){
bytes_to_read = hal_spi_em9304_rx_free_bytes();
}
// wait for data received
hal_spi_em9304_state = SPI_EM9304_RX_W4_DATA_RECEIVED;
// read all data
HAL_SPI_Receive_DMA(&hspi1, &hal_spi_em9304_rx_buffer[hal_spi_em9304_rx_pos], bytes_to_read);
hal_spi_em9304_rx_pos += bytes_to_read;
break;
case SPI_EM9304_RX_DATA_RECEIVED:
// chip deselect
HAL_GPIO_WritePin(SPI1_CSN_GPIO_Port, SPI1_CSN_Pin, GPIO_PIN_SET);
// done
hal_spi_em9304_state = SPI_EM9304_IDLE;
// transfer data
hal_spi_em9304_transfer_rx_data();
break;
case SPI_EM9304_TX_W4_RDY:
if (!hal_spi_em9304_rdy()) break;
// wait for write command sent
hal_spi_em9304_state = SPI_EM9304_TX_W4_WRITE_COMMAND_SENT;
// send write command
HAL_SPI_TransmitReceive_DMA(&hspi1, (uint8_t*) hal_spi_em9304_write_command, hal_spi_em9304_slave_status, sizeof(hal_spi_em9304_write_command));
break;
case SPI_EM9304_TX_WRITE_COMMAND_SENT:
// log_info("TX: STS1 0x%02X, STS2 0x%02X\n", hal_spi_em9304_slave_status[0], hal_spi_em9304_slave_status[1]);
// check slave status and rx buffer space
max_bytes_to_send = hal_spi_em9304_slave_status[1];
if ((hal_spi_em9304_slave_status[0] != STS_SLAVE_READY) || (max_bytes_to_send == 0)){
// chip deselect
HAL_GPIO_WritePin(SPI1_CSN_GPIO_Port, SPI1_CSN_Pin, GPIO_PIN_SET);
// retry
hal_spi_em9304_state = SPI_EM9304_IDLE;
}
bytes_to_send = hal_uart_dma_tx_size;
if (bytes_to_send > max_bytes_to_send){
bytes_to_send = max_bytes_to_send;
}
// wait for tx data sent
hal_spi_em9304_state = SPI_EM9304_TX_W4_DATA_SENT;
// send command
HAL_SPI_Transmit_DMA(&hspi1, (uint8_t*) hal_uart_dma_tx_data, bytes_to_send);
hal_uart_dma_tx_size -= bytes_to_send;
break;
case SPI_EM9304_TX_DATA_SENT:
// chip deselect
HAL_GPIO_WritePin(SPI1_CSN_GPIO_Port, SPI1_CSN_Pin, GPIO_PIN_SET);
hal_spi_em9304_state = SPI_EM9304_IDLE;
(*tx_done_handler)();
break;
default:
break;
}
}
//
// #include "hal_uart_dma.h"
static void dummy_handler(void){};
void hal_uart_dma_init(void){
hal_spi_em9304_reset();
}
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;
}
int hal_uart_dma_set_baud(uint32_t baud){
return 0;
}
void hal_uart_dma_send_block(const uint8_t *buffer, uint16_t length){
hal_uart_dma_tx_data = buffer;
hal_uart_dma_tx_size = length;
hal_spi_em9304_process();
}
void hal_uart_dma_receive_block(uint8_t *buffer, uint16_t length){
// log_info("hal_uart_dma_receive_block: len %u\n", length);
hal_uart_dma_rx_buffer = buffer;
hal_uart_dma_rx_len = length;
hal_spi_em9304_transfer_rx_data();
hal_spi_em9304_process();
}
void hal_uart_dma_set_csr_irq_handler( void (*csr_irq_handler)(void)){
}
void hal_uart_dma_set_sleep(uint8_t sleep){
}
//
static int port_test_state = 0;
static int port_test_event_len;
static uint8_t event[10];
void port_tx_done(void){
printf("HCI Reset sent\n");
}
void port_rx_done(void){
printf("EVT: ");
int i;
for (i=0;i<port_test_event_len;i++){
printf("%02x ", event[i]);
}
printf("\n");
switch(port_test_state){
case 0:
printf("Active State Entered\n");
port_test_state++;
// read active state entered event (hard coded event length)
port_test_event_len = 7;
hal_uart_dma_receive_block(event, port_test_event_len);
// next step: send reset
hal_uart_dma_send_block(hci_reset, sizeof(hci_reset));
break;
case 1:
printf("HCI Command Complete Event Received\n");
test_done = 1;
break;
default:
break;
}
}
void port_main(void){
while (1){
// setp 1: reset
printf("1. Reset: \n");
HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_RESET);
HAL_Delay(10);
HAL_GPIO_WritePin(EN_GPIO_Port, EN_Pin, GPIO_PIN_SET);
// setup hal_uart_dma
hal_uart_dma_init();
hal_uart_dma_set_block_sent(&port_tx_done);
hal_uart_dma_set_block_received(&port_rx_done);
// GO
port_test_state = 0;
test_done = 0;
// read active state entered event (hard coded event length)
port_test_event_len = 4;
hal_uart_dma_receive_block(event, port_test_event_len);
port_test_state = 0;
while (!test_done){
// wait for event / sleep
HAL_GPIO_WritePin(DEBUG_0_GPIO_Port, DEBUG_0_Pin, GPIO_PIN_SET);
while (!run_loop_triggered){};
HAL_GPIO_WritePin(DEBUG_0_GPIO_Port, DEBUG_0_Pin, GPIO_PIN_RESET);
run_loop_triggered = 0;
// handle event
hal_spi_em9304_process();
}
HAL_Delay(1000);
}
}