diff --git a/Ports/uCOS/btstack/src/btstack_memory_ucos.c b/Ports/uCOS/btstack/src/btstack_memory_ucos.c new file mode 100644 index 000000000..5438fd6fc --- /dev/null +++ b/Ports/uCOS/btstack/src/btstack_memory_ucos.c @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2011 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * btstack_memory_ucos.c + * + * @brief BTstack memory management via configurable memory pools + * + * Created by Albis Technologies. + */ + +#include + +#include "../config.h" +#include "btstack_memory.h" + +#include "hci.h" +#include "l2cap.h" +#include "rfcomm.h" + +DEFINE_THIS_FILE + +/*============================================================================= +=============================================================================*/ +static MEM_POOL hci_connection_pool; +void * btstack_memory_hci_connection_get(void) +{ + LIB_ERR err; + return Mem_PoolBlkGet(&hci_connection_pool, + sizeof(hci_connection_t), + &err); +} +void btstack_memory_hci_connection_free(void *hci_connection) +{ + LIB_ERR err; + Mem_PoolBlkFree(&hci_connection_pool, hci_connection, &err); +} + +/*============================================================================= +=============================================================================*/ +static MEM_POOL l2cap_service_pool; +void * btstack_memory_l2cap_service_get(void) +{ + LIB_ERR err; + return Mem_PoolBlkGet(&l2cap_service_pool, + sizeof(l2cap_service_t), + &err); +} +void btstack_memory_l2cap_service_free(void *l2cap_service) +{ + LIB_ERR err; + Mem_PoolBlkFree(&l2cap_service_pool, l2cap_service, &err); +} + +/*============================================================================= +=============================================================================*/ +static MEM_POOL l2cap_channel_pool; +void * btstack_memory_l2cap_channel_get(void) +{ + LIB_ERR err; + return Mem_PoolBlkGet(&l2cap_channel_pool, + sizeof(l2cap_channel_t), + &err); +} +void btstack_memory_l2cap_channel_free(void *l2cap_channel) +{ + LIB_ERR err; + Mem_PoolBlkFree(&l2cap_channel_pool, l2cap_channel, &err); +} + +/*============================================================================= +=============================================================================*/ +static MEM_POOL rfcomm_multiplexer_pool; +void * btstack_memory_rfcomm_multiplexer_get(void) +{ + LIB_ERR err; + return Mem_PoolBlkGet(&rfcomm_multiplexer_pool, + sizeof(rfcomm_multiplexer_t), + &err); +} +void btstack_memory_rfcomm_multiplexer_free(void *rfcomm_multiplexer) +{ + LIB_ERR err; + Mem_PoolBlkFree(&rfcomm_multiplexer_pool, rfcomm_multiplexer, &err); +} + +/*============================================================================= +=============================================================================*/ +static MEM_POOL rfcomm_service_pool; +void * btstack_memory_rfcomm_service_get(void) +{ + LIB_ERR err; + return Mem_PoolBlkGet(&rfcomm_service_pool, + sizeof(rfcomm_service_t), + &err); +} +void btstack_memory_rfcomm_service_free(void *rfcomm_service) +{ + LIB_ERR err; + Mem_PoolBlkFree(&rfcomm_service_pool, rfcomm_service, &err); +} + +/*============================================================================= +=============================================================================*/ +static MEM_POOL rfcomm_channel_pool; +void * btstack_memory_rfcomm_channel_get(void) +{ + LIB_ERR err; + return Mem_PoolBlkGet(&rfcomm_channel_pool, + sizeof(rfcomm_channel_t), + &err); +} +void btstack_memory_rfcomm_channel_free(void *rfcomm_channel) +{ + LIB_ERR err; + Mem_PoolBlkFree(&rfcomm_channel_pool, rfcomm_channel, &err); +} + +/*============================================================================= +=============================================================================*/ +static MEM_POOL db_mem_device_pool; +void * btstack_memory_db_mem_device_get(void){ + LIB_ERR err; + return Mem_PoolBlkGet(&db_mem_device_pool, + sizeof(db_mem_device_t), + &err); +} +void btstack_memory_db_mem_device_free(void *db_mem_device){ + LIB_ERR err; + Mem_PoolBlkFree(&db_mem_device_pool, db_mem_device, &err); +} + +/*============================================================================= +=============================================================================*/ +static MEM_POOL db_mem_service_pool; +void * btstack_memory_db_mem_service_get(void){ + LIB_ERR err; + return Mem_PoolBlkGet(&db_mem_service_pool, + sizeof(db_mem_service_t), + &err); +} +void btstack_memory_db_mem_service_free(void *db_mem_service){ + LIB_ERR err; + Mem_PoolBlkFree(&db_mem_service_pool, db_mem_service, &err); +} + +/*============================================================================= +=============================================================================*/ +void btstack_memory_init(void) +{ + LIB_ERR err; + CPU_SIZE_T octetsReqd; + + Mem_PoolCreate(&hci_connection_pool, + 0, + MAX_NO_HCI_CONNECTIONS * sizeof(hci_connection_t), + MAX_NO_HCI_CONNECTIONS, + sizeof(hci_connection_t), + sizeof(unsigned long), + &octetsReqd, + &err); + SYS_ASSERT(err == LIB_MEM_ERR_NONE); + + Mem_PoolCreate(&l2cap_service_pool, + 0, + MAX_NO_L2CAP_SERVICES * sizeof(l2cap_service_t), + MAX_NO_L2CAP_SERVICES, + sizeof(l2cap_service_t), + sizeof(unsigned long), + &octetsReqd, + &err); + SYS_ASSERT(err == LIB_MEM_ERR_NONE); + + Mem_PoolCreate(&l2cap_channel_pool, + 0, + MAX_NO_L2CAP_CHANNELS * sizeof(l2cap_channel_t), + MAX_NO_L2CAP_CHANNELS, + sizeof(l2cap_channel_t), + sizeof(unsigned long), + &octetsReqd, + &err); + SYS_ASSERT(err == LIB_MEM_ERR_NONE); + + Mem_PoolCreate(&rfcomm_multiplexer_pool, + 0, + MAX_NO_RFCOMM_MULTIPLEXERS * sizeof(rfcomm_multiplexer_t), + MAX_NO_RFCOMM_MULTIPLEXERS, + sizeof(rfcomm_multiplexer_t), + sizeof(unsigned long), + &octetsReqd, + &err); + SYS_ASSERT(err == LIB_MEM_ERR_NONE); + + Mem_PoolCreate(&rfcomm_service_pool, + 0, + MAX_NO_RFCOMM_SERVICES * sizeof(rfcomm_service_t), + MAX_NO_RFCOMM_SERVICES, + sizeof(rfcomm_service_t), + sizeof(unsigned long), + &octetsReqd, + &err); + SYS_ASSERT(err == LIB_MEM_ERR_NONE); + + Mem_PoolCreate(&rfcomm_channel_pool, + 0, + MAX_NO_RFCOMM_CHANNELS * sizeof(rfcomm_channel_t), + MAX_NO_RFCOMM_CHANNELS, + sizeof(rfcomm_channel_t), + sizeof(unsigned long), + &octetsReqd, + &err); + SYS_ASSERT(err == LIB_MEM_ERR_NONE); + + Mem_PoolCreate(&db_mem_device_pool, + 0, + MAX_NO_DB_MEM_DEVICES * sizeof(db_mem_device_t), + MAX_NO_DB_MEM_DEVICES, + sizeof(db_mem_device_t), + sizeof(unsigned long), + &octetsReqd, + &err); + SYS_ASSERT(err == LIB_MEM_ERR_NONE); + + Mem_PoolCreate(&db_mem_service_pool, + 0, + MAX_NO_DB_MEM_SERVICES * sizeof(db_mem_service_t), + MAX_NO_DB_MEM_SERVICES, + sizeof(db_mem_service_t), + sizeof(unsigned long), + &octetsReqd, + &err); + SYS_ASSERT(err == LIB_MEM_ERR_NONE); +} diff --git a/Ports/uCOS/btstack/src/hci_transport_h4_ucos.c b/Ports/uCOS/btstack/src/hci_transport_h4_ucos.c new file mode 100644 index 000000000..c0f8c5b12 --- /dev/null +++ b/Ports/uCOS/btstack/src/hci_transport_h4_ucos.c @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2011 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * hci_transport_h4_ucos.c + * + * @brief BTstack serial H4 transport for uC/OS + * + * Created by Albis Technologies. + */ + +#include + +#include "hci.h" +#include "hci_transport.h" +#include "hci_dump.h" +#include "run_loop_ucos.h" + +#include "bsp_btuart.h" + +DEFINE_THIS_FILE + +typedef enum +{ + H4_W4_PACKET_TYPE, + H4_W4_EVENT_HEADER, + H4_W4_ACL_HEADER, + H4_W4_PAYLOAD, + H4_W4_PICKUP +} H4RxState; + +static int h4_reader_process(struct data_source *ds); +static void h4_rx_data(unsigned char *data, unsigned long size); +static void dummyHandler(uint8_t packetType, uint8_t *packet, uint16_t size); +static void (*incomingPacketHandler)(uint8_t a, + uint8_t *b, + uint16_t c) = dummyHandler; +static struct +{ + data_source_t dataSource; + hci_transport_t transport; +} hciTransportH4; + +/*============================================================================= +* H4 receiver. +*============================================================================*/ +#define NOF_RX_BUFFERS 20 +#define RX_BUFFER_SIZE 1020 + +typedef struct +{ + unsigned char data[RX_BUFFER_SIZE]; + unsigned long nofBytes; +} ReceiveBuffer; + +static struct +{ + /* H4 Rx state and remaining number of Bytes in this state. */ + H4RxState state; + unsigned long remainingInState; + + /* H4 packet ring buffer and current buffer in use for Rx data. */ + ReceiveBuffer buffers[NOF_RX_BUFFERS]; + ReceiveBuffer *currBuffer; + volatile unsigned long enqueueIdx; + volatile unsigned long dequeueIdx; + volatile unsigned long nextEnqueueIdx; +}rx; + +/*============================================================================= +=============================================================================*/ +static void advanceToNextBuffer(void) +{ + rx.nextEnqueueIdx = rx.enqueueIdx + 1; + if(rx.nextEnqueueIdx >= NOF_RX_BUFFERS) + { + rx.nextEnqueueIdx = 0; + } + if(rx.nextEnqueueIdx == rx.dequeueIdx) + { + /* The ring buffer is full. */ + SYS_ERROR(1); + } + + /* Prepare current buffer for receiving. */ + rx.currBuffer = &rx.buffers[rx.enqueueIdx]; + rx.currBuffer->nofBytes = 0; +} + +/*============================================================================= +=============================================================================*/ +static int h4_open(void *config) +{ + /* Initialise H4 receiver. */ + rx.enqueueIdx = 0; + rx.dequeueIdx = 0; + advanceToNextBuffer(); + + BSP_BTUART_EnableRxCallback(h4_rx_data); + + /* Prepare for 1st H4 packet type ID. */ + rx.state = H4_W4_PACKET_TYPE; + rx.remainingInState = 1; + BSP_BTUART_AnounceDmaReceiverSize(rx.remainingInState); + + hciTransportH4.dataSource.process = h4_reader_process; + run_loop_add_data_source(&hciTransportH4.dataSource); + + return 0; +} + +/*============================================================================= +=============================================================================*/ +static int h4_close(void *config) +{ + BSP_BTUART_DisableRxCallback(); + return 0; +} + +/*============================================================================= +=============================================================================*/ +static int h4_send_packet(uint8_t packetType, uint8_t *packet, int size) +{ + hci_dump_packet(packetType, 0, packet, size); + + BSP_BTUART_Transmit(&packetType, 1); + BSP_BTUART_Transmit(packet, size); + + return 0; +} + +/*============================================================================= +=============================================================================*/ +static void h4_register_packet_handler(void (*handler)(uint8_t a, + uint8_t *b, + uint16_t c)) +{ + incomingPacketHandler = handler; +} + +/*============================================================================= +=============================================================================*/ +static void h4_rx_fsm(void) +{ + switch(rx.state) + { + case H4_W4_PACKET_TYPE: + if(rx.currBuffer->data[0] == HCI_EVENT_PACKET) + { + rx.remainingInState = HCI_EVENT_PKT_HDR; + rx.state = H4_W4_EVENT_HEADER; + } + else if(rx.currBuffer->data[0] == HCI_ACL_DATA_PACKET) + { + rx.remainingInState = HCI_ACL_DATA_PKT_HDR; + rx.state = H4_W4_ACL_HEADER; + } + else + { + rx.currBuffer->nofBytes = 0; + rx.remainingInState = 1; + } + break; + + case H4_W4_EVENT_HEADER: + rx.remainingInState = rx.currBuffer->data[2]; + rx.state = H4_W4_PAYLOAD; + break; + + case H4_W4_ACL_HEADER: + rx.remainingInState = READ_BT_16(rx.currBuffer->data, 3); + rx.state = H4_W4_PAYLOAD; + break; + + case H4_W4_PAYLOAD: + rx.state = H4_W4_PICKUP; + break; + + default: + break; + } + + if(rx.remainingInState) + { + BSP_BTUART_AnounceDmaReceiverSize(rx.remainingInState); + } +} + +/*============================================================================= +=============================================================================*/ +static int h4_reader_process(struct data_source *ds) +{ + unsigned long pickUpSize; + unsigned char *pickUpBuffer; + unsigned long nextDequeueIdx; + + pickUpSize = rx.buffers[rx.dequeueIdx].nofBytes - 1; + pickUpBuffer = rx.buffers[rx.dequeueIdx].data; + + /* Handle complete incoming HCI packet. */ + SYS_ASSERT(pickUpSize >= 2); + + hci_dump_packet(*pickUpBuffer, 1, pickUpBuffer + 1, pickUpSize); + incomingPacketHandler(*pickUpBuffer, pickUpBuffer + 1, pickUpSize); + + nextDequeueIdx = rx.dequeueIdx + 1; + if(nextDequeueIdx >= NOF_RX_BUFFERS) + { + nextDequeueIdx = 0; + } + rx.dequeueIdx = nextDequeueIdx; + + return 0; +} + +/*============================================================================= +=============================================================================*/ +static void h4_rx_data(unsigned char *data, unsigned long size) +{ + unsigned long i; + + SYS_ASSERT(size + rx.currBuffer->nofBytes <= RX_BUFFER_SIZE); + SYS_ASSERT(size <= rx.remainingInState); + + /* Copy from DMA buffer to Rx buffer (no memcpy() or Mem_Copy()). */ + for(i = 0; i < size; ++i) + { + rx.currBuffer->data[rx.currBuffer->nofBytes + i] = data[i]; + } + + rx.currBuffer->nofBytes += size; + rx.remainingInState -= size; + + if(rx.remainingInState == 0) + { + h4_rx_fsm(); + + if(rx.state == H4_W4_PICKUP) + { + /* Advance to next Rx buffer. */ + rx.enqueueIdx = rx.nextEnqueueIdx; + advanceToNextBuffer(); + + /* Prepare for next H4 packet type ID. */ + rx.state = H4_W4_PACKET_TYPE; + rx.remainingInState = 1; + BSP_BTUART_AnounceDmaReceiverSize(rx.remainingInState); + + /* Notify complete Rx packet. */ + run_loop_notify_incoming_transport_packet(); + } + } +} + +/*============================================================================= +=============================================================================*/ +static int h4_set_baudrate(uint32_t baudrate) +{ + BSP_BTUART_SetBaudrate(baudrate); + return 0; +} + +/*============================================================================= +=============================================================================*/ +const char * h4_transport_name(void) +{ + return "H4"; +} + +/*============================================================================= +=============================================================================*/ +static void dummyHandler(uint8_t packetType, uint8_t *packet, uint16_t size) +{ +} + +/*============================================================================= +* H4 transport instance. +*============================================================================*/ +hci_transport_t * hci_transport_h4_instance(void) +{ + hciTransportH4.transport.open = h4_open; + hciTransportH4.transport.close = h4_close; + hciTransportH4.transport.send_packet = h4_send_packet; + hciTransportH4.transport.register_packet_handler = h4_register_packet_handler; + hciTransportH4.transport.get_transport_name = h4_transport_name; + hciTransportH4.transport.set_baudrate = h4_set_baudrate; + + return &hciTransportH4.transport; +} diff --git a/Ports/uCOS/btstack/src/port_ucos.c b/Ports/uCOS/btstack/src/port_ucos.c new file mode 100644 index 000000000..b3bbd592d --- /dev/null +++ b/Ports/uCOS/btstack/src/port_ucos.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2009 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * port_ucos.c + * + * uC/OS porting layer. + * + * Created by Albis Technologies. + */ + +#include + +#include "../config.h" + +/*============================================================================= +=============================================================================*/ +int gettimeofday(struct timeval *tv, void *tzp) +{ + INT32U ticks = OSTimeGet(); + + tv->tv_sec = ticks / OS_TICKS_PER_SEC; + tv->tv_usec = (ticks - (tv->tv_sec * OS_TICKS_PER_SEC)) * + (1000000UL / OS_TICKS_PER_SEC); + + return 0; +} + +/*============================================================================= +=============================================================================*/ +uint32_t embedded_get_ticks(void) +{ + return OSTimeGet(); +} + +/*============================================================================= +=============================================================================*/ +uint32_t embedded_ticks_for_ms(uint32_t time_in_ms) +{ + return MSEC_TO_TICKS(time_in_ms); +} + +/*============================================================================= +=============================================================================*/ +int gethostname(char *name, size_t len) +{ + Str_Copy_N((CPU_CHAR *)name, (CPU_CHAR *)BT_DEV_NAME, len - 1); + return 0; +} diff --git a/Ports/uCOS/btstack/src/port_ucos.h b/Ports/uCOS/btstack/src/port_ucos.h new file mode 100644 index 000000000..91852cb90 --- /dev/null +++ b/Ports/uCOS/btstack/src/port_ucos.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2009 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * port_ucos.h + * + * uC/OS porting layer. + * + * Created by Albis Technologies. + */ + +#ifndef PORT_UCOS_H +#define PORT_UCOS_H + +/* uC/OS-II include files. */ +#include +#include +#include + +/* These standard includes are allowed. */ +#include +#include + +/* OS version depending macros. */ +#define USE_OS_NO_ERROR OS_NO_ERR +#define USE_OS_TIMEOUT OS_TIMEOUT + +/* Convert msec to OS ticks. */ +#define MSEC_TO_TICKS(ms) \ + ((ms > 0u) ? (((ms * OS_TICKS_PER_SEC) + 1000u - 1u) / 1000u) : 0u) + +/* Map stdlib functions to uC/LIB ones. */ +#define memcpy(a, b, c) (Mem_Copy((void *)(a), (void *)(b), c)) +#define memset(a, b, c) (Mem_Set((void *)(a), b, c)) +#define bzero(a, c) (Mem_Set((void *)(a), 0, c)) +#define memcmp(a, b, c) (!Mem_Cmp((void *)(a), (void *)(b), c)) +#define strncpy(a, b, c) (Str_Copy_N((CPU_CHAR *)(a), (CPU_CHAR *)b, c)) +#define strncmp(a, b, c) (Str_Cmp_N((CPU_CHAR *)(a), (CPU_CHAR *)b, c)) +#define strlen(a) (Str_Len((CPU_CHAR *)(a))) + +extern void * memmove(void *dst, const void *src, unsigned int length); + +/* There are no such uC-LIB implementations. */ +#define sprintf(a, b, ...) __error__ +#define sscanf(a, ...) __error__ + +/* Time function. */ +struct timeval +{ + unsigned long tv_sec; + unsigned long tv_usec; +}; +int gettimeofday(struct timeval *tv, void *tzp); + +/* Host name. */ +int gethostname(char *name, size_t len); + +/* Debug output. */ +#include "bsp_debug.h" + +#define ENABLE_BTSTACK_DEBUG_OUTPUT 0 + +#if(ENABLE_BTSTACK_DEBUG_OUTPUT == 1) + #define printf(...) { printos(__VA_ARGS__); } + #define fprintf(_fd, ...) { printos(__VA_ARGS__); } + #define log_debug(...) { printos(__VA_ARGS__); } + #define log_info(...) { printos(__VA_ARGS__); } + #define log_error(...) { printos(__VA_ARGS__); } +#else + #define printf(...) + #define fprintf(_fd, ...) + #define log_debug(...) + #define log_info(...) + #define log_error(...) +#endif /* ENABLE_BTSTACK_DEBUG_OUTPUT */ + +#endif /* PORT_UCOS_H */ diff --git a/Ports/uCOS/btstack/src/run_loop_ucos.c b/Ports/uCOS/btstack/src/run_loop_ucos.c new file mode 100644 index 000000000..2a0001cc6 --- /dev/null +++ b/Ports/uCOS/btstack/src/run_loop_ucos.c @@ -0,0 +1,172 @@ +/* + * Copyright (C) 2011 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * run_loop_ucos.c + * + * @brief BTstack run loop for uC/OS + * + * Created by Albis Technologies. + */ + +#include +#include + +#include "run_loop_ucos.h" +#include "hci_transport.h" +#include "serial.h" + +DEFINE_THIS_FILE + +static linked_list_t timers; +static data_source_t *transportDataSource = 0; + +/*============================================================================= +* Run loop message queue. +*============================================================================*/ +#define MSG_QUEUE_BUFFER_SIZE 32 + +#define MSG_ID_INCOMING_TRANSPORT_PACKET 1 +#define MSG_ID_OUTGOING_RFCOMM_DATA 2 + +static struct +{ + OS_EVENT *queue; + void * queueBuffer[MSG_QUEUE_BUFFER_SIZE]; +} messages; + +/*============================================================================= +=============================================================================*/ +void run_loop_notify_incoming_transport_packet(void) +{ + INT8U err; + + err = OSQPost(messages.queue, (void *)MSG_ID_INCOMING_TRANSPORT_PACKET); + SYS_ASSERT(err == USE_OS_NO_ERROR); +} + +/*============================================================================= +=============================================================================*/ +void run_loop_notify_outgoing_rfcomm_data(void) +{ + INT8U err; + + err = OSQPost(messages.queue, (void *)MSG_ID_OUTGOING_RFCOMM_DATA); + SYS_ASSERT(err == USE_OS_NO_ERROR); +} + +/*============================================================================= +=============================================================================*/ +void run_loop_add_data_source(data_source_t *ds) +{ + transportDataSource = ds; +} + +/*============================================================================= +=============================================================================*/ +void run_loop_add_timer(timer_source_t *ts) +{ + linked_item_t *it; + + for(it = (linked_item_t *)&timers; it->next; it = it->next) + { + if(ts->timeout < ((timer_source_t *)it->next)->timeout) + { + break; + } + } + + ts->item.next = it->next; + it->next = (linked_item_t *)ts; +} + +/*============================================================================= +=============================================================================*/ +void run_loop_set_timer(timer_source_t *ts, uint32_t timeout_in_ms) +{ + unsigned long ticks = MSEC_TO_TICKS(timeout_in_ms); + ts->timeout = OSTimeGet() + ticks; +} + +/*============================================================================= +=============================================================================*/ +int run_loop_remove_timer(timer_source_t *ts) +{ + return linked_list_remove(&timers, (linked_item_t *) ts); +} + +/*============================================================================= +=============================================================================*/ +void run_loop_execute(void) +{ + INT8U err; + void *event; + INT16U timeout; + + for(;;) + { + /* Get next timeout. */ + timeout = 0; + if(timers) + { + timeout = ((timer_source_t *)timers)->timeout - OSTimeGet(); + } + + event = OSQPend(messages.queue, timeout, &err); + + if(err == USE_OS_NO_ERROR) + { + if((unsigned long)event == MSG_ID_INCOMING_TRANSPORT_PACKET) + { + transportDataSource->process(transportDataSource); + } + } + + /* Process timers. */ + while(timers) + { + timer_source_t *ts = (timer_source_t *)timers; + if(ts->timeout > OSTimeGet()) break; + run_loop_remove_timer(ts); + ts->process(ts); + } + } +} + +/*============================================================================= +=============================================================================*/ +void run_loop_init(RUN_LOOP_TYPE type) +{ + timers = 0; + + messages.queue = OSQCreate(messages.queueBuffer, MSG_QUEUE_BUFFER_SIZE); + SYS_ASSERT(messages.queue); +} diff --git a/Ports/uCOS/btstack/src/run_loop_ucos.h b/Ports/uCOS/btstack/src/run_loop_ucos.h new file mode 100644 index 000000000..b50c9e32e --- /dev/null +++ b/Ports/uCOS/btstack/src/run_loop_ucos.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2011 by Matthias Ringwald + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the names of + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY MATTHIAS RINGWALD AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS + * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + */ + +/* + * run_loop_ucos.h + * + * @brief BTstack run loop for uC/OS + * + * Created by Albis Technologies. + */ + +#pragma once + +void run_loop_notify_incoming_transport_packet(void); diff --git a/Ports/uCOS/example/Makefile b/Ports/uCOS/example/Makefile new file mode 100644 index 000000000..119212e32 --- /dev/null +++ b/Ports/uCOS/example/Makefile @@ -0,0 +1,199 @@ +#============================================================================== +# (C) Copyright Albis Technologies Ltd 2011 +#============================================================================== +# STM32 Example Code +#============================================================================== +# File name: Makefile +# +# Notes: - +#============================================================================== + +firsttarget: all + +include project.settings + +SHELL=/bin/bash.exe +GCC=arm-none-eabi-gcc.exe +AS=arm-none-eabi-as.exe +OBJCPY=arm-none-eabi-objcopy +RM=rm +ECHO=echo + +#============================================================================== +# Building. +#============================================================================== +AFLAGS=-mcpu=cortex-m3 \ + +CFLAGS=-Wall \ + -Wpointer-arith \ + -Wstrict-prototypes \ + -Werror \ + -mcpu=cortex-m3 \ + -mthumb \ + -g \ + -O2 \ + $(LED_DEFINES) \ + +LFLAGS=-nostartfiles \ + -nostdlib \ + -mcpu=cortex-m3 \ + +.s.o: + $(AS) $(AFLAGS) -c $< -o $@ + +.c.o: + $(GCC) $(CFLAGS) $(INCL) -c $< -o $@ + +#============================================================================== +# Repository directories. +#============================================================================== +PATH_OS_SRC=../../../../uCOS-II/Source +PATH_CM3_SRC=../../../../uCOS-II/Ports/ARM-Cortex-M3/Generic/GNU +PATH_BSP_SRC=.. +PATH_CPU_SRC=../../../../uC-CPU/ARM-Cortex-M3/GNU +PATH_CPU_INC=../../../../uC-CPU +PATH_UCLIB_SRC=../../../../uC-LIB +PATH_STM32_SRC=../../../../CPU/ST/STM32/src +PATH_STM32_INC=../../../../CPU/ST/STM32/inc +PATH_BTSTACK_SRC=../../../../../../BTstack/src +PATH_BTSTACK_INC=../../../../../../BTstack/include +PATH_APPL_SRC=../../../../../../Application +PATH_APPL_INC=../../../../../../Application + +#============================================================================== +# Board support package (BSP). +#============================================================================== +ASMS_START=vector_table.o \ + +OBJS_BSP=$(PATH_BSP_SRC)/app_hooks.o \ + $(PATH_BSP_SRC)/bsp.o \ + $(PATH_BSP_SRC)/bsp_debug.o \ + $(PATH_BSP_SRC)/bsp_i2c.o \ + $(PATH_BSP_SRC)/bsp_int.o \ + $(PATH_BSP_SRC)/bsp_periph.o \ + $(PATH_BSP_SRC)/bsp_stlm75.o \ + $(PATH_BSP_SRC)/main.o \ + $(PATH_BSP_SRC)/T32_Term.o \ + $(PATH_BSP_SRC)/uCOS-II/bsp_os.o \ + vector_funcs.o \ + +ifeq ($(STM32_USART_DMA),yes) + OBJS_BSP+=$(PATH_BSP_SRC)/bsp_btuart_dma.o +else + OBJS_BSP+=$(PATH_BSP_SRC)/bsp_btuart_nodma.o +endif + +INCL_BSP=-I$(PATH_BSP_SRC) \ + -I$(PATH_BSP_SRC)/uCOS-II + +#============================================================================== +# uC/OS-II. +#============================================================================== +ASMS_UCOS=$(PATH_CM3_SRC)/os_cpu_a.o \ + $(PATH_CPU_SRC)/cpu_a.o \ + +OBJS_UCOS=$(PATH_OS_SRC)/os_core.o \ + $(PATH_OS_SRC)/os_flag.o \ + $(PATH_OS_SRC)/os_mbox.o \ + $(PATH_OS_SRC)/os_mem.o \ + $(PATH_OS_SRC)/os_mutex.o \ + $(PATH_OS_SRC)/os_q.o \ + $(PATH_OS_SRC)/os_sem.o \ + $(PATH_OS_SRC)/os_task.o \ + $(PATH_OS_SRC)/os_time.o \ + $(PATH_OS_SRC)/os_tmr.o \ + $(PATH_CM3_SRC)/os_cpu_c.o \ + $(PATH_CM3_SRC)/os_dbg.o \ + $(PATH_CPU_SRC)/cpu_c.o + +INCL_UCOS=-I$(PATH_OS_SRC) \ + -I$(PATH_CM3_SRC) \ + -I$(PATH_CPU_SRC) \ + -I$(PATH_CPU_INC) \ + +#============================================================================== +# uC/LIB. +#============================================================================== +OBJS_UCLIB=$(PATH_UCLIB_SRC)/lib_mem.o \ + $(PATH_UCLIB_SRC)/lib_str.o \ + $(PATH_UCLIB_SRC)/memmove.o \ + +INCL_UCLIB=-I$(PATH_UCLIB_SRC) \ + +#============================================================================== +# STM32. +#============================================================================== +OBJS_STM32=$(PATH_STM32_SRC)/stm32f10x_flash.o \ + $(PATH_STM32_SRC)/stm32f10x_gpio.o \ + $(PATH_STM32_SRC)/stm32f10x_rcc.o \ + $(PATH_STM32_SRC)/stm32f10x_usart.o \ + +ifeq ($(STM32_USART_DMA),yes) + OBJS_STM32+=$(PATH_STM32_SRC)/stm32f10x_dma.o $(PATH_STM32_SRC)/misc.o +endif + +INCL_STM32=-I$(PATH_STM32_INC) \ + -I$(PATH_STM32_SRC) \ + +#============================================================================== +# BTstack. +#============================================================================== +OBJS_BTSTACK=$(PATH_BTSTACK_SRC)/btstack_memory_ucos.o \ + $(PATH_BTSTACK_SRC)/daemon.o \ + $(PATH_BTSTACK_SRC)/hci.o \ + $(PATH_BTSTACK_SRC)/hci_cmds.o \ + $(PATH_BTSTACK_SRC)/hci_dump_ucos.o \ + $(PATH_BTSTACK_SRC)/hci_transport_h4_ucos.o \ + $(PATH_BTSTACK_SRC)/l2cap.o \ + $(PATH_BTSTACK_SRC)/l2cap_signaling.o \ + $(PATH_BTSTACK_SRC)/linked_list.o \ + $(PATH_BTSTACK_SRC)/port_ucos.o \ + $(PATH_BTSTACK_SRC)/remote_device_db_memory.o \ + $(PATH_BTSTACK_SRC)/rfcomm.o \ + $(PATH_BTSTACK_SRC)/run_loop_ucos.o \ + $(PATH_BTSTACK_SRC)/sdp.o \ + $(PATH_BTSTACK_SRC)/sdp_util.o \ + $(PATH_BTSTACK_SRC)/sdp_spp_record.o \ + $(PATH_BTSTACK_SRC)/utils.o \ + +ifeq ($(BT_CHIPSET),CSR_BC4) + OBJS_BTSTACK+=$(PATH_BTSTACK_SRC)/bt_chipset_csrbc4.o + CFLAGS+=-DBT_CHIPSET_CSR_BC4=1 + CFLAGS+=-DBT_CHIPSET_CSR_BC4_CHANGE_BAUDRATE=$(CSR_BC4_CHANGE_BAUDRATE_ID) +endif + +ifeq ($(BT_CHIPSET),PAN1315) + OBJS_BTSTACK+=$(PATH_BTSTACK_SRC)/bt_chipset_pan1315.o + OBJS_BTSTACK+=$(PATH_BTSTACK_SRC)/pan1315_init.o + CFLAGS+=-DBT_CHIPSET_PAN1315=1 +endif + +INCL_BTSTACK=-I$(PATH_BTSTACK_INC) \ + -I$(PATH_BTSTACK_SRC) \ + +#============================================================================== +# Application. +#============================================================================== +OBJS_APPL=$(PATH_APPL_SRC)/api.o \ + $(PATH_APPL_SRC)/serial.o \ + +INCL_APPL=-I$(PATH_APPL_INC) + +#============================================================================== +# All objects for binary. +#============================================================================== +ASMS=$(ASMS_START) $(ASMS_UCOS) +OBJS=$(OBJS_BSP) $(OBJS_UCOS) $(OBJS_UCLIB) $(OBJS_STM32) $(OBJS_BTSTACK) $(OBJS_APPL) +INCL=$(INCL_BSP) $(INCL_UCOS) $(INCL_UCLIB) $(INCL_STM32) $(INCL_BTSTACK) $(INCL_APPL) +BIN=btstackfw + +all: $(ASMS) $(OBJS) + @$(ECHO) Linking Flash image... + $(GCC) $(LFLAGS) -Wl,-Map,$(BIN).map -Tlinker.lds -o $(BIN).elf $(ASMS) $(OBJS) + $(OBJCPY) -O binary $(BIN).elf $(BIN).bin + @$(ECHO) + @$(ECHO) Successfully built BTstack Flash image for $(BT_CHIPSET), STM32 UART DMA $(STM32_USART_DMA). + @$(ECHO) + +clean: + $(RM) -f *.elf *.bin *.map $(ASMS) $(OBJS) diff --git a/Ports/uCOS/example/project.settings b/Ports/uCOS/example/project.settings new file mode 100644 index 000000000..09340b5a4 --- /dev/null +++ b/Ports/uCOS/example/project.settings @@ -0,0 +1,74 @@ +#============================================================================== +# (C) Copyright Albis Technologies Ltd 2011 +#============================================================================== +# Example Code +#============================================================================== +# File name: project.settings +# +# Notes: - +#============================================================================== + +# Choose evaluation board. Available: +# EVAL_BOARD=MICRIUM (UM0780) +# EVAL_BOARD=OLIMEX (STM32-P107) +EVAL_BOARD=MICRIUM + +# Choose Bluetooth chipset. Available: +# BT_CHIPSET=CSR_BC4 (CSR BlueCore4) +# BT_CHIPSET=PAN1315 (Panasonic PAN1315) +BT_CHIPSET=CSR_BC4 + +# CSR BlueCore4 only : change to higher baud rate during initialisation. +# Set 0 for no change. +# 1 : 38400 +# 2 : 57600 +# 3 : 115200 +# 4 : 230400 +# 5 : 460800 +# 6 : 500000 +# 7 : 921600 +ifeq ($(BT_CHIPSET),CSR_BC4) + CSR_BC4_CHANGE_BAUDRATE_ID=6 +endif + +# Choose whether or not STM32 USART DMA in use [yes|no]. +STM32_USART_DMA=no + +# Notification LEDs. +# +# Micrium STM32 evaluation board UM0780 +# Green : PD13 +# Orange : PD14 +# Red : PD15 +# +# Olimex STM32 evaluation board STM32-P107 +# Green : PC6 +# Orange : PC7 +# Red : none +ifeq ($(EVAL_BOARD),MICRIUM) + LED_PORT=4 + LED_GREEN_PRESENT=1 + LED_GREEN=13 + LED_ORANGE_PRESENT=1 + LED_ORANGE=14 + LED_RED_PRESENT=1 + LED_RED=15 +endif + +ifeq ($(EVAL_BOARD),OLIMEX) + LED_PORT=3 + LED_GREEN_PRESENT=1 + LED_GREEN=6 + LED_ORANGE_PRESENT=1 + LED_ORANGE=7 + LED_RED_PRESENT=0 + LED_RED=0 +endif + +LED_DEFINES=-DLED_PORT=$(LED_PORT) +LED_DEFINES+=-DLED_GREEN_PRESENT=$(LED_GREEN_PRESENT) +LED_DEFINES+=-DLED_GREEN=$(LED_GREEN) +LED_DEFINES+=-DLED_ORANGE_PRESENT=$(LED_ORANGE_PRESENT) +LED_DEFINES+=-DLED_ORANGE=$(LED_ORANGE) +LED_DEFINES+=-DLED_RED_PRESENT=$(LED_RED_PRESENT) +LED_DEFINES+=-DLED_RED=$(LED_RED) diff --git a/Ports/uCOS/stm32/src/bsp_btuart.h b/Ports/uCOS/stm32/src/bsp_btuart.h new file mode 100644 index 000000000..736306f75 --- /dev/null +++ b/Ports/uCOS/stm32/src/bsp_btuart.h @@ -0,0 +1,156 @@ +/*============================================================================= +* (C) Copyright Albis Technologies Ltd 2011 +*============================================================================== +* STM32 Example Code +*============================================================================== +* File name: bsp_btuart.h +* +* Notes: STM32 Bluetooth UART driver. +*============================================================================*/ + +#ifndef BSP_BTUART_H +#define BSP_BTUART_H + +/*============================================================================= +* Prototype of receiver callback function. +=============================================================================*/ +typedef void(* RxCallbackFunc)(unsigned char *data, unsigned long size); + +/*============================================================================= +* PURPOSE: Initialising Bluetooth UART. +* +* PARAMETERS: +* - +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_Initialise(void); + +/*============================================================================= +* PURPOSE: Setting Bluetooth UART baud rate. +* +* PARAMETERS: +* baudrate - baud rate to set. +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_SetBaudrate(unsigned long baudrate); + +/*============================================================================= +* PURPOSE: Activating BT chip reset. +* +* PARAMETERS: +* - +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_ActivateReset(void); + +/*============================================================================= +* PURPOSE: Deactivating BT chip reset. +* +* PARAMETERS: +* - +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_DeactivateReset(void); + +/*============================================================================= +* PURPOSE: Sending on Bluetooth UART. +* +* PARAMETERS: +* buffer - pointer to buffer to send. +* count - number of bytes to send. +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_Transmit(unsigned char *buffer, unsigned long count); + +/*============================================================================= +* PURPOSE: Anouncing DMA receiver size. +* +* PARAMETERS: +* count - number of bytes to receive with DMA. +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_AnounceDmaReceiverSize(unsigned long count); + +/*============================================================================= +* PURPOSE: Receiving on Bluetooth UART without receiver callback. +* +* PARAMETERS: +* buffer - pointer to buffer for received bytes. +* maxCount - maximal number of bytes buffer can hold. +* rxCount - output: pointer to number of received bytes. +* timeout - timeout in msec, zero = wait forever. +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_Receive(unsigned char *buffer, + unsigned long maxCount, + unsigned long *rxCount, + unsigned long timeout); + +/*============================================================================= +* PURPOSE: Draining bytes already received. +* +* PARAMETERS: +* - +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_DrainReceiver(void); + +/*============================================================================= +* PURPOSE: Enabling Bluetooth receiver callback. +* +* PARAMETERS: +* callbackFunc - receiver callback function. +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_EnableRxCallback(RxCallbackFunc callbackFunc); + +/*============================================================================= +* PURPOSE: Disabling Bluetooth receiver callback. +* +* PARAMETERS: +* - +* +* RETURN VALUE: +* - +* +* COMMENTS: - +=============================================================================*/ +void BSP_BTUART_DisableRxCallback(void); + +#endif /* BSP_BTUART_H */ diff --git a/Ports/uCOS/stm32/src/bsp_btuart_dma.c b/Ports/uCOS/stm32/src/bsp_btuart_dma.c new file mode 100644 index 000000000..aa39a21cf --- /dev/null +++ b/Ports/uCOS/stm32/src/bsp_btuart_dma.c @@ -0,0 +1,300 @@ +/*============================================================================= +* (C) Copyright Albis Technologies Ltd 2011 +*============================================================================== +* STM32 Example Code +*============================================================================== +* File name: bsp_btuart_dma.c +* +* Notes: STM32 Bluetooth UART driver with DMA. +*============================================================================*/ + +#include "bsp.h" +#include "bsp_btuart.h" +#include "bsp_debug.h" + +#include "stm32f10x_dma.h" +#include "stm32f10x_gpio.h" +#include "stm32f10x_dma.h" +#include "stm32f10x_usart.h" + +DEFINE_THIS_FILE + +/* OS version depending macros. */ +#define USE_OS_NO_ERROR OS_NO_ERR +#define USE_OS_TIMEOUT OS_TIMEOUT +#define USE_OS_Q_FULL OS_Q_FULL + +/* PD2 is BT chipset reset. */ +#define BT_RESET_PIN (1UL << 2) + +/* BT UART is USART2 (remapped). */ +#define BTUART_INST_IN_USE USART2 + +/* Convert msec to OS ticks. */ +#define MSEC_TO_TICKS(ms) \ + ((ms > 0u) ? (((ms * OS_TICKS_PER_SEC) + 1000u - 1u) / 1000u) : 0u) + +/* USART instance in use. */ +static USART_TypeDef *usartInst = 0; + +/* UART receiver with callback. */ +static RxCallbackFunc rxCallbackFunc = 0; + +/* DMA channels for Rx/Tx. */ +static OS_EVENT *dmaRxComplete = 0; +static OS_EVENT *dmaTxComplete = 0; +static DMA_Channel_TypeDef *dmaRx; +static DMA_Channel_TypeDef *dmaTx; +static unsigned long dmaRxDataLength; +static unsigned char dmaRxData[1024]; + +/*============================================================================= +=============================================================================*/ +static void isr_usart_rx_dma(void) +{ + INT8U err; + + DMA_ClearITPendingBit(DMA1_IT_TC6); + DMA_Cmd(dmaRx, DISABLE); + + if(rxCallbackFunc) + { + rxCallbackFunc(dmaRxData, dmaRxDataLength); + } + else + { + err = OSSemPost(dmaRxComplete); + SYS_ASSERT(err == USE_OS_NO_ERROR); + } +} + +/*============================================================================= +=============================================================================*/ +static void isr_usart_tx_dma(void) +{ + INT8U err; + + DMA_ClearITPendingBit(DMA1_IT_TC7); + + err = OSSemPost(dmaTxComplete); + SYS_ASSERT(err == USE_OS_NO_ERROR); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_Initialise(void) +{ + DMA_InitTypeDef dmaInit; + GPIO_InitTypeDef gpioInit; + NVIC_InitTypeDef nvicInit; + USART_ClockInitTypeDef usartClkInit; + + /* UART instance in use. */ + usartInst = BTUART_INST_IN_USE; + + /* DMA Rx/Tx complete. */ + dmaRxComplete = OSSemCreate(0); + SYS_ASSERT(dmaRxComplete); + dmaTxComplete = OSSemCreate(0); + SYS_ASSERT(dmaTxComplete); + + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); + + /* Common DMA channel settings. */ + DMA_StructInit(&dmaInit); + dmaInit.DMA_PeripheralBaseAddr = (unsigned long)&usartInst->DR; + dmaInit.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + dmaInit.DMA_MemoryInc = DMA_MemoryInc_Enable; + dmaInit.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + dmaInit.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + dmaInit.DMA_Mode = DMA_Mode_Normal; + dmaInit.DMA_M2M = DMA_M2M_Disable; + dmaInit.DMA_BufferSize = 1; + + /* Init DMA Tx channel MEM -> USART. */ + dmaTx = DMA1_Channel7; + dmaInit.DMA_Priority = DMA_Priority_Low; + dmaInit.DMA_DIR = DMA_DIR_PeripheralDST; + BSP_IntVectSet(BSP_INT_ID_DMA1_CH7, isr_usart_tx_dma); + DMA_Init(dmaTx, &dmaInit); + DMA_ITConfig(dmaTx, DMA_IT_TC, ENABLE); + USART_DMACmd(usartInst, USART_DMAReq_Tx, ENABLE); + + /* Init DMA Rx channel USART -> MEM. */ + dmaRx = DMA1_Channel6; + dmaInit.DMA_Priority = DMA_Priority_Medium; + dmaInit.DMA_DIR = DMA_DIR_PeripheralSRC; + BSP_IntVectSet(BSP_INT_ID_DMA1_CH6, isr_usart_rx_dma); + DMA_Init(dmaRx, &dmaInit); + DMA_ITConfig(dmaRx, DMA_IT_TC, ENABLE); + USART_DMACmd(usartInst, USART_DMAReq_Rx, ENABLE); + + nvicInit.NVIC_IRQChannelPreemptionPriority = 0; + nvicInit.NVIC_IRQChannelSubPriority = 0; + nvicInit.NVIC_IRQChannelCmd = ENABLE; + + nvicInit.NVIC_IRQChannel = DMA1_Channel6_IRQn; + NVIC_Init(&nvicInit); + + nvicInit.NVIC_IRQChannel = DMA1_Channel7_IRQn; + NVIC_Init(&nvicInit); + + USART_ClockStructInit(&usartClkInit); + usartClkInit.USART_Clock = USART_Clock_Disable; + usartClkInit.USART_CPOL = USART_CPOL_Low; + usartClkInit.USART_CPHA = USART_CPHA_2Edge; + usartClkInit.USART_LastBit = USART_LastBit_Disable; + + BSP_PeriphEn(BSP_PERIPH_ID_USART2); + + BSP_PeriphEn(BSP_PERIPH_ID_IOPD); + BSP_PeriphEn(BSP_PERIPH_ID_AFIO); + GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE); + + /* Configure GPIOD.5 (TX) as push-pull. */ + gpioInit.GPIO_Pin = GPIO_Pin_5; + gpioInit.GPIO_Speed = GPIO_Speed_50MHz; + gpioInit.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOD, &gpioInit); + + /* Configure GPIOD.4 (RTS) as push-pull. */ + gpioInit.GPIO_Pin = GPIO_Pin_4; + gpioInit.GPIO_Speed = GPIO_Speed_50MHz; + gpioInit.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOD, &gpioInit); + + /* Configure GPIOD.6 (RX) as input floating. */ + gpioInit.GPIO_Pin = GPIO_Pin_6; + gpioInit.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOD, &gpioInit); + + /* Configure GPIOD.3 (CTS) as input floating. */ + gpioInit.GPIO_Pin = GPIO_Pin_3; + gpioInit.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOD, &gpioInit); + + BSP_BTUART_SetBaudrate(115200); + USART_ClockInit(usartInst, &usartClkInit); + USART_Cmd(usartInst, ENABLE); + + /* GPO for BT chipset reset. */ + gpioInit.GPIO_Pin = BT_RESET_PIN; + gpioInit.GPIO_Speed = GPIO_Speed_50MHz; + gpioInit.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_Init(GPIOD, &gpioInit); + + BSP_BTUART_ActivateReset(); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_SetBaudrate(unsigned long baudrate) +{ + USART_InitTypeDef usartInit; + + USART_StructInit(&usartInit); + usartInit.USART_BaudRate = baudrate / 2; + usartInit.USART_WordLength = USART_WordLength_8b; + usartInit.USART_StopBits = USART_StopBits_1; + usartInit.USART_Parity = USART_Parity_No; + usartInit.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS; + usartInit.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + + USART_Init(usartInst, &usartInit); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_ActivateReset(void) +{ + GPIO_ResetBits(GPIOD, BT_RESET_PIN); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_DeactivateReset(void) +{ + GPIO_SetBits(GPIOD, BT_RESET_PIN); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_Transmit(unsigned char *buffer, unsigned long count) +{ + INT8U err; + + dmaTx->CMAR = (unsigned long)buffer; + dmaTx->CNDTR = count; + + DMA_Cmd(dmaTx, ENABLE); + + OSSemPend(dmaTxComplete, MSEC_TO_TICKS(2000), &err); + if(err == USE_OS_TIMEOUT) + { + DMA_Cmd(dmaTx, DISABLE); + return; + } + SYS_ASSERT(err == USE_OS_NO_ERROR); + + DMA_Cmd(dmaTx, DISABLE); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_AnounceDmaReceiverSize(unsigned long count) +{ + dmaRx->CMAR = (unsigned long)(&dmaRxData[0]); + dmaRx->CNDTR = count; + dmaRxDataLength = count; + + DMA_Cmd(dmaRx, ENABLE); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_Receive(unsigned char *buffer, + unsigned long maxCount, + unsigned long *rxCount, + unsigned long timeout) +{ + INT8U err; + unsigned short timeoutTicks = MSEC_TO_TICKS(timeout); + + rxCallbackFunc = 0; + + BSP_BTUART_AnounceDmaReceiverSize(maxCount); + + OSSemPend(dmaRxComplete, timeoutTicks, &err); + if(err == USE_OS_TIMEOUT) + { + *rxCount = 0; + return; + } + SYS_ASSERT(err == USE_OS_NO_ERROR); + + Mem_Copy(buffer, dmaRxData, dmaRxDataLength); + *rxCount = dmaRxDataLength; +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_DrainReceiver(void) +{ + /* Nothing to do. */ +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_EnableRxCallback(RxCallbackFunc callbackFunc) +{ + rxCallbackFunc = callbackFunc; +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_DisableRxCallback(void) +{ + rxCallbackFunc = 0; +} diff --git a/Ports/uCOS/stm32/src/bsp_btuart_nodma.c b/Ports/uCOS/stm32/src/bsp_btuart_nodma.c new file mode 100644 index 000000000..edc166e67 --- /dev/null +++ b/Ports/uCOS/stm32/src/bsp_btuart_nodma.c @@ -0,0 +1,270 @@ +/*============================================================================= +* (C) Copyright Albis Technologies Ltd 2011 +*============================================================================== +* STM32 Example Code +*============================================================================== +* File name: bsp_btuart_nodma.c +* +* Notes: STM32 Bluetooth UART driver without DMA. +*============================================================================*/ + +#include "bsp.h" +#include "bsp_btuart.h" +#include "bsp_debug.h" + +#include "stm32f10x_gpio.h" +#include "stm32f10x_usart.h" + +DEFINE_THIS_FILE + +/* OS version depending macros. */ +#define USE_OS_NO_ERROR OS_NO_ERR +#define USE_OS_TIMEOUT OS_TIMEOUT +#define USE_OS_Q_FULL OS_Q_FULL + +/* PD2 is BT chipset reset. */ +#define BT_RESET_PIN (1UL << 2) + +/* BT UART is USART2 (remapped). */ +#define BTUART_INST_IN_USE USART2 + +/* Convert msec to OS ticks. */ +#define MSEC_TO_TICKS(ms) \ + ((ms > 0u) ? (((ms * OS_TICKS_PER_SEC) + 1000u - 1u) / 1000u) : 0u) + +/* USART instance in use. */ +static USART_TypeDef *usartInst = 0; + +/* UART receiver without callback. */ +#define RX_QUEUE_BUFFER_SIZE 512 +static OS_EVENT *rxQueue = 0; +static void * rxQueueBuffer[RX_QUEUE_BUFFER_SIZE]; + +/* UART receiver with callback. */ +static RxCallbackFunc rxCallbackFunc = 0; + +//============================================================================= +//============================================================================= +static void isr_bluetooth_usart(void) +{ + INT8U err; + CPU_INT32U rxData; + + if(USART_GetITStatus(usartInst, USART_IT_RXNE) != RESET) + { + rxData = USART_ReceiveData(usartInst) & 0xff; + + if(rxCallbackFunc) + { + rxCallbackFunc((unsigned char *)&rxData, 1); + } + else + { + err = OSQPost(rxQueue, (void *)rxData); + if(err == USE_OS_NO_ERROR) + { + // Ok. + } + else if(err == USE_OS_Q_FULL) + { + printos("Tossing BT data!\r\n"); + } + else + { + SYS_ERROR(1); + } + } + + USART_ClearITPendingBit(usartInst, USART_IT_RXNE); + } + else + { + SYS_ERROR(1); + } +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_Initialise(void) +{ + GPIO_InitTypeDef gpioInit; + USART_ClockInitTypeDef usartClkInit; + + /* UART instance in use. */ + usartInst = BTUART_INST_IN_USE; + + /* Create Rx queue. */ + rxQueue = OSQCreate(rxQueueBuffer, RX_QUEUE_BUFFER_SIZE); + SYS_ASSERT(rxQueue); + + USART_ClockStructInit(&usartClkInit); + usartClkInit.USART_Clock = USART_Clock_Disable; + usartClkInit.USART_CPOL = USART_CPOL_Low; + usartClkInit.USART_CPHA = USART_CPHA_2Edge; + usartClkInit.USART_LastBit = USART_LastBit_Disable; + + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); + BSP_PeriphEn(BSP_PERIPH_ID_USART2); + + BSP_PeriphEn(BSP_PERIPH_ID_IOPD); + BSP_PeriphEn(BSP_PERIPH_ID_AFIO); + GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE); + + /* Configure GPIOD.5 (TX) as push-pull. */ + gpioInit.GPIO_Pin = GPIO_Pin_5; + gpioInit.GPIO_Speed = GPIO_Speed_50MHz; + gpioInit.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOD, &gpioInit); + + /* Configure GPIOD.4 (RTS) as push-pull. */ + gpioInit.GPIO_Pin = GPIO_Pin_4; + gpioInit.GPIO_Speed = GPIO_Speed_50MHz; + gpioInit.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(GPIOD, &gpioInit); + + /* Configure GPIOD.6 (RX) as input floating. */ + gpioInit.GPIO_Pin = GPIO_Pin_6; + gpioInit.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOD, &gpioInit); + + /* Configure GPIOD.3 (CTS) as input floating. */ + gpioInit.GPIO_Pin = GPIO_Pin_3; + gpioInit.GPIO_Mode = GPIO_Mode_IN_FLOATING; + GPIO_Init(GPIOD, &gpioInit); + + BSP_BTUART_SetBaudrate(115200); + USART_ClockInit(usartInst, &usartClkInit); + USART_Cmd(usartInst, ENABLE); + + BSP_IntVectSet(BSP_INT_ID_USART2, isr_bluetooth_usart); + BSP_IntEn(BSP_INT_ID_USART2); + USART_ITConfig(usartInst, USART_IT_RXNE, ENABLE); + + /* GPO for BT chipset reset. */ + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD, ENABLE); + gpioInit.GPIO_Pin = BT_RESET_PIN; + gpioInit.GPIO_Speed = GPIO_Speed_50MHz; + gpioInit.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_Init(GPIOD, &gpioInit); + + BSP_BTUART_ActivateReset(); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_SetBaudrate(unsigned long baudrate) +{ + USART_InitTypeDef usartInit; + + USART_StructInit(&usartInit); + usartInit.USART_BaudRate = baudrate / 2; + usartInit.USART_WordLength = USART_WordLength_8b; + usartInit.USART_StopBits = USART_StopBits_1; + usartInit.USART_Parity = USART_Parity_No; + usartInit.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS; + usartInit.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; + + USART_Init(usartInst, &usartInit); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_ActivateReset(void) +{ + GPIO_ResetBits(GPIOD, BT_RESET_PIN); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_DeactivateReset(void) +{ + GPIO_SetBits(GPIOD, BT_RESET_PIN); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_Transmit(unsigned char *buffer, unsigned long count) +{ + unsigned long i; + + for(i = 0; i < count; ++i) + { + while(USART_GetFlagStatus(usartInst, USART_FLAG_TXE) != SET); + USART_SendData(usartInst, buffer[i]); + } +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_AnounceDmaReceiverSize(unsigned long count) +{ + /* Nothing to do: no DMA. */ +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_Receive(unsigned char *buffer, + unsigned long maxCount, + unsigned long *rxCount, + unsigned long timeout) +{ + INT8U err; + void *event = 0; + unsigned long rxCounter = 0; + unsigned short timeoutTicks = MSEC_TO_TICKS(timeout); + + for(;;) + { + event = OSQPend(rxQueue, timeoutTicks, &err); + + if(err == USE_OS_NO_ERROR) + { + buffer[rxCounter++] = (unsigned char)(unsigned long)event; + + if(rxCounter >= maxCount) + { + // Received expected number of bytes. + break; + } + } + else if(err == USE_OS_TIMEOUT) + { + break; + } + else + { + SYS_ERROR(1); + } + } + + if(rxCount) + { + *rxCount = rxCounter; + } +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_DrainReceiver(void) +{ + INT8U err; + + do + { + OSQPend(rxQueue, 1, &err); + } while(err == OS_ERR_NONE); +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_EnableRxCallback(RxCallbackFunc callbackFunc) +{ + rxCallbackFunc = callbackFunc; +} + +/*============================================================================= +=============================================================================*/ +void BSP_BTUART_DisableRxCallback(void) +{ + rxCallbackFunc = 0; +}