xref: /btstack/port/apollo2-em9304/btstack_port.c (revision c8dfe071e5be306bdac290dfbe6cbf2b9a446e88)
1905e80caSMatthias Ringwald //
2905e80caSMatthias Ringwald // BTstack port for Apolle 2 EVB with EM9304 shield
3905e80caSMatthias Ringwald //
4905e80caSMatthias Ringwald 
5905e80caSMatthias Ringwald #include "am_mcu_apollo.h"
6905e80caSMatthias Ringwald #include "am_bsp.h"
7905e80caSMatthias Ringwald #include "am_util.h"
8905e80caSMatthias Ringwald #include "am_devices_em9304.h"
9905e80caSMatthias Ringwald 
10905e80caSMatthias Ringwald //*****************************************************************************
11905e80caSMatthias Ringwald //
12905e80caSMatthias Ringwald // Insert compiler version at compile time.
13905e80caSMatthias Ringwald //
14905e80caSMatthias Ringwald //*****************************************************************************
15905e80caSMatthias Ringwald #define STRINGIZE_VAL(n)                    STRINGIZE_VAL2(n)
16905e80caSMatthias Ringwald #define STRINGIZE_VAL2(n)                   #n
17905e80caSMatthias Ringwald 
18905e80caSMatthias Ringwald #ifdef __GNUC__
19905e80caSMatthias Ringwald #define COMPILER_VERSION                    ("GCC " __VERSION__)
20905e80caSMatthias Ringwald #elif defined(__ARMCC_VERSION)
21905e80caSMatthias Ringwald #define COMPILER_VERSION                    ("ARMCC " STRINGIZE_VAL(__ARMCC_VERSION))
22905e80caSMatthias Ringwald #elif defined(__KEIL__)
23905e80caSMatthias Ringwald #define COMPILER_VERSION                    "KEIL_CARM " STRINGIZE_VAL(__CA__)
24905e80caSMatthias Ringwald #elif defined(__IAR_SYSTEMS_ICC__)
25905e80caSMatthias Ringwald #define COMPILER_VERSION                    __VERSION__
26905e80caSMatthias Ringwald #else
27905e80caSMatthias Ringwald #define COMPILER_VERSION                    "Compiler unknown"
28905e80caSMatthias Ringwald #endif
29905e80caSMatthias Ringwald 
30905e80caSMatthias Ringwald //*****************************************************************************
31905e80caSMatthias Ringwald //
32905e80caSMatthias Ringwald // IOM SPI Configuration for EM9304
33905e80caSMatthias Ringwald //
34905e80caSMatthias Ringwald //*****************************************************************************
35905e80caSMatthias Ringwald const am_hal_iom_config_t g_sEm9304IOMConfigSPI =
36905e80caSMatthias Ringwald {
37905e80caSMatthias Ringwald     .ui32ClockFrequency = AM_HAL_IOM_8MHZ,
38905e80caSMatthias Ringwald     .ui32InterfaceMode = AM_HAL_IOM_SPIMODE,
39905e80caSMatthias Ringwald     .ui8WriteThreshold = 20,
40905e80caSMatthias Ringwald     .ui8ReadThreshold = 20,
41905e80caSMatthias Ringwald     .bSPHA = 0,
42905e80caSMatthias Ringwald     .bSPOL = 0,
43905e80caSMatthias Ringwald };
44905e80caSMatthias Ringwald 
45905e80caSMatthias Ringwald //*****************************************************************************
46905e80caSMatthias Ringwald //
47905e80caSMatthias Ringwald // UART configuration settings.
48905e80caSMatthias Ringwald //
49905e80caSMatthias Ringwald //*****************************************************************************
50905e80caSMatthias Ringwald am_hal_uart_config_t g_sUartConfig =
51905e80caSMatthias Ringwald {
52905e80caSMatthias Ringwald     .ui32BaudRate = 115200,
53905e80caSMatthias Ringwald     .ui32DataBits = AM_HAL_UART_DATA_BITS_8,
54905e80caSMatthias Ringwald     .bTwoStopBits = false,
55905e80caSMatthias Ringwald     .ui32Parity   = AM_HAL_UART_PARITY_NONE,
56905e80caSMatthias Ringwald     .ui32FlowCtrl = AM_HAL_UART_FLOW_CTRL_NONE,
57905e80caSMatthias Ringwald };
58905e80caSMatthias Ringwald 
59905e80caSMatthias Ringwald //*****************************************************************************
60905e80caSMatthias Ringwald //
61905e80caSMatthias Ringwald // Initialize the UART
62905e80caSMatthias Ringwald //
63905e80caSMatthias Ringwald //*****************************************************************************
64905e80caSMatthias Ringwald void
uart_init(uint32_t ui32Module)65905e80caSMatthias Ringwald uart_init(uint32_t ui32Module)
66905e80caSMatthias Ringwald {
67905e80caSMatthias Ringwald     //
68905e80caSMatthias Ringwald     // Make sure the UART RX and TX pins are enabled.
69905e80caSMatthias Ringwald     //
70905e80caSMatthias Ringwald     am_bsp_pin_enable(COM_UART_TX);
71905e80caSMatthias Ringwald     am_bsp_pin_enable(COM_UART_RX);
72905e80caSMatthias Ringwald 
73905e80caSMatthias Ringwald     //
74905e80caSMatthias Ringwald     // Power on the selected UART
75905e80caSMatthias Ringwald     //
76905e80caSMatthias Ringwald     am_hal_uart_pwrctrl_enable(ui32Module);
77905e80caSMatthias Ringwald 
78905e80caSMatthias Ringwald     //
79905e80caSMatthias Ringwald     // Start the UART interface, apply the desired configuration settings, and
80905e80caSMatthias Ringwald     // enable the FIFOs.
81905e80caSMatthias Ringwald     //
82905e80caSMatthias Ringwald     am_hal_uart_clock_enable(ui32Module);
83905e80caSMatthias Ringwald 
84905e80caSMatthias Ringwald     //
85905e80caSMatthias Ringwald     // Disable the UART before configuring it.
86905e80caSMatthias Ringwald     //
87905e80caSMatthias Ringwald     am_hal_uart_disable(ui32Module);
88905e80caSMatthias Ringwald 
89905e80caSMatthias Ringwald     //
90905e80caSMatthias Ringwald     // Configure the UART.
91905e80caSMatthias Ringwald     //
92905e80caSMatthias Ringwald     am_hal_uart_config(ui32Module, &g_sUartConfig);
93905e80caSMatthias Ringwald 
94905e80caSMatthias Ringwald     //
95905e80caSMatthias Ringwald     // Enable the UART FIFO.
96905e80caSMatthias Ringwald     //
97905e80caSMatthias Ringwald     am_hal_uart_fifo_config(ui32Module, AM_HAL_UART_TX_FIFO_1_2 | AM_HAL_UART_RX_FIFO_1_2);
98905e80caSMatthias Ringwald 
99905e80caSMatthias Ringwald     //
100905e80caSMatthias Ringwald     // Enable the UART.
101905e80caSMatthias Ringwald     //
102905e80caSMatthias Ringwald     am_hal_uart_enable(ui32Module);
103905e80caSMatthias Ringwald }
104905e80caSMatthias Ringwald 
105905e80caSMatthias Ringwald //*****************************************************************************
106905e80caSMatthias Ringwald //
107905e80caSMatthias Ringwald // Disable the UART
108905e80caSMatthias Ringwald //
109905e80caSMatthias Ringwald //*****************************************************************************
110905e80caSMatthias Ringwald void
uart_disable(uint32_t ui32Module)111905e80caSMatthias Ringwald uart_disable(uint32_t ui32Module)
112905e80caSMatthias Ringwald {
113905e80caSMatthias Ringwald     //
114905e80caSMatthias Ringwald     // Clear all interrupts before sleeping as having a pending UART interrupt
115905e80caSMatthias Ringwald     // burns power.
116905e80caSMatthias Ringwald     //
117905e80caSMatthias Ringwald     am_hal_uart_int_clear(ui32Module, 0xFFFFFFFF);
118905e80caSMatthias Ringwald 
119905e80caSMatthias Ringwald     //
120905e80caSMatthias Ringwald     // Disable the UART.
121905e80caSMatthias Ringwald     //
122905e80caSMatthias Ringwald     am_hal_uart_disable(ui32Module);
123905e80caSMatthias Ringwald 
124905e80caSMatthias Ringwald     //
125905e80caSMatthias Ringwald     // Disable the UART pins.
126905e80caSMatthias Ringwald     //
127905e80caSMatthias Ringwald     am_bsp_pin_disable(COM_UART_TX);
128905e80caSMatthias Ringwald     am_bsp_pin_disable(COM_UART_RX);
129905e80caSMatthias Ringwald 
130905e80caSMatthias Ringwald     //
131905e80caSMatthias Ringwald     // Disable the UART clock.
132905e80caSMatthias Ringwald     //
133905e80caSMatthias Ringwald     am_hal_uart_clock_disable(ui32Module);
134905e80caSMatthias Ringwald }
135905e80caSMatthias Ringwald 
136905e80caSMatthias Ringwald //*****************************************************************************
137905e80caSMatthias Ringwald //
138905e80caSMatthias Ringwald // Initialize the EM9304 BLE Controller
139905e80caSMatthias Ringwald //
140905e80caSMatthias Ringwald //*****************************************************************************
141905e80caSMatthias Ringwald void
am_devices_em9304_spi_init(uint32_t ui32Module,const am_hal_iom_config_t * psIomConfig)142905e80caSMatthias Ringwald am_devices_em9304_spi_init(uint32_t ui32Module, const am_hal_iom_config_t *psIomConfig)
143905e80caSMatthias Ringwald {
144905e80caSMatthias Ringwald     if ( AM_REGn(IOMSTR, ui32Module, CFG) & AM_REG_IOMSTR_CFG_IFCEN_M )
145905e80caSMatthias Ringwald     {
146905e80caSMatthias Ringwald         return;
147905e80caSMatthias Ringwald     }
148905e80caSMatthias Ringwald 
149905e80caSMatthias Ringwald #if defined(AM_PART_APOLLO2)
150905e80caSMatthias Ringwald     am_hal_iom_pwrctrl_enable(ui32Module);
151905e80caSMatthias Ringwald #endif
152905e80caSMatthias Ringwald     //
153905e80caSMatthias Ringwald     // Setup the pins for SPI mode.
154905e80caSMatthias Ringwald     //
155905e80caSMatthias Ringwald     am_bsp_iom_spi_pins_enable(ui32Module);
156905e80caSMatthias Ringwald 
157905e80caSMatthias Ringwald     //
158905e80caSMatthias Ringwald     // Set the required configuration settings for the IOM.
159905e80caSMatthias Ringwald     //
160905e80caSMatthias Ringwald     am_hal_iom_config(ui32Module, psIomConfig);
161905e80caSMatthias Ringwald 
162905e80caSMatthias Ringwald     // Enable spi
163905e80caSMatthias Ringwald     am_hal_iom_enable(ui32Module);
164905e80caSMatthias Ringwald }
165905e80caSMatthias Ringwald 
166905e80caSMatthias Ringwald void
configure_em9304_pins(void)167905e80caSMatthias Ringwald configure_em9304_pins(void)
168905e80caSMatthias Ringwald {
169905e80caSMatthias Ringwald     am_bsp_pin_enable(EM9304_CS);
170905e80caSMatthias Ringwald     am_bsp_pin_enable(EM9304_INT);
171905e80caSMatthias Ringwald 
172905e80caSMatthias Ringwald     am_hal_gpio_out_bit_set(AM_BSP_GPIO_EM9304_CS);
173905e80caSMatthias Ringwald 
174905e80caSMatthias Ringwald     am_hal_gpio_int_polarity_bit_set(AM_BSP_GPIO_EM9304_INT, AM_HAL_GPIO_RISING);
175905e80caSMatthias Ringwald     am_hal_gpio_int_clear(AM_HAL_GPIO_BIT(AM_BSP_GPIO_EM9304_INT));
176905e80caSMatthias Ringwald     am_hal_gpio_int_enable(AM_HAL_GPIO_BIT(AM_BSP_GPIO_EM9304_INT));
177905e80caSMatthias Ringwald }
178905e80caSMatthias Ringwald 
179905e80caSMatthias Ringwald void
em9304_init(void)180905e80caSMatthias Ringwald em9304_init(void)
181905e80caSMatthias Ringwald {
182905e80caSMatthias Ringwald     //
183905e80caSMatthias Ringwald     // Assert RESET to the Telink device.
184905e80caSMatthias Ringwald     //
185905e80caSMatthias Ringwald     am_hal_gpio_pin_config(AM_BSP_GPIO_EM9304_RESET, AM_HAL_GPIO_OUTPUT);
186905e80caSMatthias Ringwald     am_hal_gpio_out_bit_clear(AM_BSP_GPIO_EM9304_RESET);
187905e80caSMatthias Ringwald 
188905e80caSMatthias Ringwald     //
189905e80caSMatthias Ringwald     // Setup SPI interface for EM9304
190905e80caSMatthias Ringwald     //
191905e80caSMatthias Ringwald     configure_em9304_pins();
192905e80caSMatthias Ringwald     am_devices_em9304_spi_init(AM_BSP_EM9304_IOM, &g_sEm9304IOMConfigSPI);
193905e80caSMatthias Ringwald 
194905e80caSMatthias Ringwald     //
195905e80caSMatthias Ringwald     // Delay for 20ms to make sure the em device gets ready for commands.
196905e80caSMatthias Ringwald     //
197905e80caSMatthias Ringwald     am_util_delay_ms(5);
198905e80caSMatthias Ringwald 
199905e80caSMatthias Ringwald     //
200905e80caSMatthias Ringwald     // Enable the IOM and GPIO interrupt handlers.
201905e80caSMatthias Ringwald     //
202905e80caSMatthias Ringwald     am_hal_gpio_out_bit_set(AM_BSP_GPIO_EM9304_RESET);
203905e80caSMatthias Ringwald 
204905e80caSMatthias Ringwald     am_util_delay_ms(20);
205905e80caSMatthias Ringwald }
206905e80caSMatthias Ringwald 
207905e80caSMatthias Ringwald // hal_cpu.h implementation
208905e80caSMatthias Ringwald #include "hal_cpu.h"
209905e80caSMatthias Ringwald 
hal_cpu_disable_irqs(void)210905e80caSMatthias Ringwald void hal_cpu_disable_irqs(void){
211905e80caSMatthias Ringwald     am_hal_interrupt_master_disable();
212905e80caSMatthias Ringwald }
213905e80caSMatthias Ringwald 
hal_cpu_enable_irqs(void)214905e80caSMatthias Ringwald void hal_cpu_enable_irqs(void){
215905e80caSMatthias Ringwald     am_hal_interrupt_master_enable();
216905e80caSMatthias Ringwald }
217905e80caSMatthias Ringwald 
hal_cpu_enable_irqs_and_sleep(void)218905e80caSMatthias Ringwald void hal_cpu_enable_irqs_and_sleep(void){
219905e80caSMatthias Ringwald     am_hal_interrupt_master_enable();
220905e80caSMatthias Ringwald     __asm__("wfe"); // go to sleep if event flag isn't set. if set, just clear it. IRQs set event flag
221905e80caSMatthias Ringwald }
222905e80caSMatthias Ringwald 
223905e80caSMatthias Ringwald 
224905e80caSMatthias Ringwald // hal_time_ms.h
225905e80caSMatthias Ringwald #include "hal_time_ms.h"
hal_time_ms(void)226905e80caSMatthias Ringwald uint32_t hal_time_ms(void){
227c5ae0d23SMatthias Ringwald     return am_hal_stimer_counter_get();
228905e80caSMatthias Ringwald }
229905e80caSMatthias Ringwald 
230905e80caSMatthias Ringwald 
231905e80caSMatthias Ringwald /**
232905e80caSMatthias Ringwald  * Use USART_CONSOLE as a console.
233905e80caSMatthias Ringwald  * This is a syscall for newlib
234905e80caSMatthias Ringwald  * @param file
235905e80caSMatthias Ringwald  * @param ptr
236905e80caSMatthias Ringwald  * @param len
237905e80caSMatthias Ringwald  * @return
238905e80caSMatthias Ringwald  */
239905e80caSMatthias Ringwald #include <stdio.h>
240905e80caSMatthias Ringwald #include <unistd.h>
241905e80caSMatthias Ringwald #include <errno.h>
242905e80caSMatthias Ringwald int _write(int file, char *ptr, int len);
_write(int file,char * ptr,int len)243905e80caSMatthias Ringwald int _write(int file, char *ptr, int len){
244905e80caSMatthias Ringwald #if 1
245905e80caSMatthias Ringwald   uint8_t cr = '\r';
246905e80caSMatthias Ringwald   int i;
247905e80caSMatthias Ringwald 
248905e80caSMatthias Ringwald   if (file == STDOUT_FILENO || file == STDERR_FILENO) {
249905e80caSMatthias Ringwald     for (i = 0; i < len; i++) {
250905e80caSMatthias Ringwald       if (ptr[i] == '\n') {
251905e80caSMatthias Ringwald         am_hal_uart_char_transmit_polled( AM_BSP_UART_PRINT_INST, cr );
252905e80caSMatthias Ringwald     }
253905e80caSMatthias Ringwald     am_hal_uart_char_transmit_polled( AM_BSP_UART_PRINT_INST, ptr[i]);
254905e80caSMatthias Ringwald }
255905e80caSMatthias Ringwald return i;
256905e80caSMatthias Ringwald }
257905e80caSMatthias Ringwald errno = EIO;
258905e80caSMatthias Ringwald return -1;
259905e80caSMatthias Ringwald #else
260905e80caSMatthias Ringwald   return len;
261905e80caSMatthias Ringwald #endif
262905e80caSMatthias Ringwald }
_read(int file,char * ptr,int len)263905e80caSMatthias Ringwald int _read(int file, char * ptr, int len){
264905e80caSMatthias Ringwald   (void)file;
265905e80caSMatthias Ringwald   (void)ptr;
266905e80caSMatthias Ringwald   (void)len;
267905e80caSMatthias Ringwald   return -1;
268905e80caSMatthias Ringwald }
269905e80caSMatthias Ringwald 
_close(int file)270905e80caSMatthias Ringwald int _close(int file){
271905e80caSMatthias Ringwald   (void)file;
272905e80caSMatthias Ringwald   return -1;
273905e80caSMatthias Ringwald }
274905e80caSMatthias Ringwald 
_isatty(int file)275905e80caSMatthias Ringwald int _isatty(int file){
276905e80caSMatthias Ringwald   (void)file;
277905e80caSMatthias Ringwald   return -1;
278905e80caSMatthias Ringwald }
279905e80caSMatthias Ringwald 
_lseek(int file)280905e80caSMatthias Ringwald int _lseek(int file){
281905e80caSMatthias Ringwald   (void)file;
282905e80caSMatthias Ringwald   return -1;
283905e80caSMatthias Ringwald }
284905e80caSMatthias Ringwald 
_fstat(int file)285905e80caSMatthias Ringwald int _fstat(int file){
286905e80caSMatthias Ringwald   (void)file;
287905e80caSMatthias Ringwald   return -1;
288905e80caSMatthias Ringwald }
289905e80caSMatthias Ringwald 
_sbrk(intptr_t increment)290905e80caSMatthias Ringwald void * _sbrk(intptr_t increment){
291905e80caSMatthias Ringwald   return (void*) -1;
292905e80caSMatthias Ringwald }
293905e80caSMatthias Ringwald 
294905e80caSMatthias Ringwald 
295905e80caSMatthias Ringwald // hal_em9304_spi.h
296905e80caSMatthias Ringwald #include "hal_em9304_spi.h"
297905e80caSMatthias Ringwald 
298905e80caSMatthias Ringwald static void (*hal_em9304_spi_transfer_done_callback)(void);
299905e80caSMatthias Ringwald static void (*hal_em9304_spi_ready_callback)(void);
300905e80caSMatthias Ringwald 
301905e80caSMatthias Ringwald #if (0 == AM_BSP_EM9304_IOM)
302905e80caSMatthias Ringwald void
am_iomaster0_isr(void)303905e80caSMatthias Ringwald am_iomaster0_isr(void)
304905e80caSMatthias Ringwald {
305905e80caSMatthias Ringwald     uint32_t ui32IntStatus;
306905e80caSMatthias Ringwald 
307905e80caSMatthias Ringwald     //
308905e80caSMatthias Ringwald     // Read and clear the interrupt status.
309905e80caSMatthias Ringwald     //
310905e80caSMatthias Ringwald     ui32IntStatus = am_hal_iom_int_status_get(0, false);
311905e80caSMatthias Ringwald     am_hal_iom_int_clear(0, ui32IntStatus);
312905e80caSMatthias Ringwald 
313905e80caSMatthias Ringwald     //
314905e80caSMatthias Ringwald     // Service FIFO interrupts as necessary, and call IOM callbacks as
315905e80caSMatthias Ringwald     // transfers are completed.
316905e80caSMatthias Ringwald     //
317905e80caSMatthias Ringwald     am_hal_iom_int_service(0, ui32IntStatus);
318905e80caSMatthias Ringwald }
319905e80caSMatthias Ringwald #endif
320905e80caSMatthias Ringwald 
321905e80caSMatthias Ringwald #if defined(AM_PART_APOLLO2)
322905e80caSMatthias Ringwald #if (5 == AM_BSP_EM9304_IOM)
323905e80caSMatthias Ringwald void
am_iomaster5_isr(void)324905e80caSMatthias Ringwald am_iomaster5_isr(void)
325905e80caSMatthias Ringwald {
326905e80caSMatthias Ringwald     uint32_t ui32IntStatus;
327905e80caSMatthias Ringwald 
328905e80caSMatthias Ringwald     //
329905e80caSMatthias Ringwald     // Read and clear the interrupt status.
330905e80caSMatthias Ringwald     //
331905e80caSMatthias Ringwald     ui32IntStatus = am_hal_iom_int_status_get(5, false);
332905e80caSMatthias Ringwald     am_hal_iom_int_clear(5, ui32IntStatus);
333905e80caSMatthias Ringwald 
334905e80caSMatthias Ringwald     //
335905e80caSMatthias Ringwald     // Service FIFO interrupts as necessary, and call IOM callbacks as
336905e80caSMatthias Ringwald     // transfers are completed.
337905e80caSMatthias Ringwald     //
338905e80caSMatthias Ringwald     am_hal_iom_int_service(5, ui32IntStatus);
339905e80caSMatthias Ringwald }
340905e80caSMatthias Ringwald #endif
341905e80caSMatthias Ringwald #endif
342905e80caSMatthias Ringwald 
343905e80caSMatthias Ringwald void
am_gpio_isr(void)344905e80caSMatthias Ringwald am_gpio_isr(void)
345905e80caSMatthias Ringwald {
346905e80caSMatthias Ringwald     uint64_t ui64Status;
347905e80caSMatthias Ringwald 
348905e80caSMatthias Ringwald     //
349905e80caSMatthias Ringwald     // Check and clear the GPIO interrupt status
350905e80caSMatthias Ringwald     //
351905e80caSMatthias Ringwald     ui64Status = am_hal_gpio_int_status_get(true);
352905e80caSMatthias Ringwald     am_hal_gpio_int_clear(ui64Status);
353905e80caSMatthias Ringwald 
354905e80caSMatthias Ringwald     //
355905e80caSMatthias Ringwald     // Check to see if this was a wakeup event from the BLE radio.
356905e80caSMatthias Ringwald     //
357905e80caSMatthias Ringwald     if ( ui64Status & AM_HAL_GPIO_BIT(AM_BSP_GPIO_EM9304_INT) )
358905e80caSMatthias Ringwald     {
359905e80caSMatthias Ringwald         if (hal_em9304_spi_ready_callback){
360905e80caSMatthias Ringwald             (*hal_em9304_spi_ready_callback)();
361905e80caSMatthias Ringwald         }
362905e80caSMatthias Ringwald     }
363905e80caSMatthias Ringwald }
364905e80caSMatthias Ringwald 
hal_em9304_spi_enable_ready_interrupt(void)365905e80caSMatthias Ringwald void hal_em9304_spi_enable_ready_interrupt(void){
366905e80caSMatthias Ringwald     am_hal_gpio_int_enable(AM_HAL_GPIO_BIT(AM_BSP_GPIO_EM9304_INT));
367905e80caSMatthias Ringwald }
368905e80caSMatthias Ringwald 
hal_em9304_spi_disable_ready_interrupt(void)369905e80caSMatthias Ringwald void hal_em9304_spi_disable_ready_interrupt(void){
370905e80caSMatthias Ringwald     am_hal_gpio_int_disable(AM_HAL_GPIO_BIT(AM_BSP_GPIO_EM9304_INT));
371905e80caSMatthias Ringwald }
372905e80caSMatthias Ringwald 
hal_em9304_spi_set_ready_callback(void (* done)(void))373905e80caSMatthias Ringwald void hal_em9304_spi_set_ready_callback(void (*done)(void)){
374905e80caSMatthias Ringwald     hal_em9304_spi_ready_callback = done;
375905e80caSMatthias Ringwald }
376905e80caSMatthias Ringwald 
hal_em9304_spi_get_ready(void)377905e80caSMatthias Ringwald int hal_em9304_spi_get_ready(void){
378905e80caSMatthias Ringwald     return am_hal_gpio_input_read() & AM_HAL_GPIO_BIT(AM_BSP_GPIO_EM9304_INT);
379905e80caSMatthias Ringwald }
380905e80caSMatthias Ringwald 
hal_em9304_spi_init(void)381905e80caSMatthias Ringwald void hal_em9304_spi_init(void){
382905e80caSMatthias Ringwald     hal_em9304_spi_disable_ready_interrupt();
383905e80caSMatthias Ringwald }
384905e80caSMatthias Ringwald 
hal_em9304_spi_deinit(void)385905e80caSMatthias Ringwald void hal_em9304_spi_deinit(void){
386905e80caSMatthias Ringwald     hal_em9304_spi_disable_ready_interrupt();
387905e80caSMatthias Ringwald }
388905e80caSMatthias Ringwald 
hal_em9304_spi_set_transfer_done_callback(void (* done)(void))389905e80caSMatthias Ringwald void hal_em9304_spi_set_transfer_done_callback(void (*done)(void)){
390905e80caSMatthias Ringwald     hal_em9304_spi_transfer_done_callback = done;
391905e80caSMatthias Ringwald }
392905e80caSMatthias Ringwald 
hal_em9304_spi_set_chip_select(int enable)393905e80caSMatthias Ringwald void hal_em9304_spi_set_chip_select(int enable){
394905e80caSMatthias Ringwald     if (enable){
395905e80caSMatthias Ringwald         am_hal_gpio_out_bit_clear(AM_BSP_GPIO_EM9304_CS);
396905e80caSMatthias Ringwald     } else {
397905e80caSMatthias Ringwald         am_hal_gpio_out_bit_set(AM_BSP_GPIO_EM9304_CS);
398905e80caSMatthias Ringwald     }
399905e80caSMatthias Ringwald }
400905e80caSMatthias Ringwald 
hal_em9304_spi_transceive(const uint8_t * tx_data,uint8_t * rx_data,uint16_t len)401905e80caSMatthias Ringwald void hal_em9304_spi_transceive(const uint8_t * tx_data, uint8_t * rx_data, uint16_t len){
402905e80caSMatthias Ringwald     // TODO: handle tx_data/rx_data not aligned
403905e80caSMatthias Ringwald     // TODO: support non-blocking full duplex
404905e80caSMatthias Ringwald     uint32_t ui32ChipSelect = 0;
405905e80caSMatthias Ringwald     // TODO: Use Full Duplex with Interrupt callback
406905e80caSMatthias Ringwald     // NOTE: Full Duplex only supported on Apollo2
407905e80caSMatthias Ringwald     // NOTE: Enabling Full Duplex causes am_hal_iom_spi_write_nq to block (as bytes ready returns number of bytes written)
408905e80caSMatthias Ringwald     // AM_REGn(IOMSTR, ui32Module, CFG) |= AM_REG_IOMSTR_CFG_FULLDUP(1);
409905e80caSMatthias Ringwald     am_hal_iom_spi_fullduplex_nq(AM_BSP_EM9304_IOM, ui32ChipSelect, (uint32_t *) tx_data, (uint32_t *) rx_data, len, AM_HAL_IOM_RAW);
410905e80caSMatthias Ringwald     (*hal_em9304_spi_transfer_done_callback)();
411905e80caSMatthias Ringwald     return;
412905e80caSMatthias Ringwald }
413905e80caSMatthias Ringwald 
hal_em9304_spi_transmit(const uint8_t * tx_data,uint16_t len)414905e80caSMatthias Ringwald void hal_em9304_spi_transmit(const uint8_t * tx_data, uint16_t len){
415905e80caSMatthias Ringwald     // TODO: handle tx_data/rx_data not aligned
416905e80caSMatthias Ringwald     uint32_t ui32ChipSelect = 0;
417905e80caSMatthias Ringwald     am_hal_iom_spi_write_nb(AM_BSP_EM9304_IOM, ui32ChipSelect, (uint32_t *) tx_data, len, AM_HAL_IOM_RAW, hal_em9304_spi_transfer_done_callback);
418905e80caSMatthias Ringwald }
419905e80caSMatthias Ringwald 
hal_em9304_spi_receive(uint8_t * rx_data,uint16_t len)420905e80caSMatthias Ringwald void hal_em9304_spi_receive(uint8_t * rx_data, uint16_t len){
421905e80caSMatthias Ringwald     // TODO: handle tx_data/rx_data not aligned
422905e80caSMatthias Ringwald     // TODO: support non-blocking full duplex
423905e80caSMatthias Ringwald     uint32_t ui32ChipSelect = 0;
424905e80caSMatthias Ringwald     am_hal_iom_spi_read_nb(AM_BSP_EM9304_IOM, ui32ChipSelect, (uint32_t *) rx_data, len, AM_HAL_IOM_RAW, hal_em9304_spi_transfer_done_callback);
425905e80caSMatthias Ringwald }
426905e80caSMatthias Ringwald 
hal_em9304_spi_get_fullduplex_support(void)427905e80caSMatthias Ringwald int hal_em9304_spi_get_fullduplex_support(void){
428905e80caSMatthias Ringwald     return 0;
429905e80caSMatthias Ringwald }
430905e80caSMatthias Ringwald 
431905e80caSMatthias Ringwald //*****************************************************************************
432905e80caSMatthias Ringwald //
433905e80caSMatthias Ringwald // Main
434905e80caSMatthias Ringwald //
435905e80caSMatthias Ringwald //*****************************************************************************
436905e80caSMatthias Ringwald 
437905e80caSMatthias Ringwald 
438905e80caSMatthias Ringwald // EM 9304 SPI Master HCI Implementation
439905e80caSMatthias Ringwald const uint8_t hci_reset_2[] = { 0x01, 0x03, 0x0c, 0x00 };
440905e80caSMatthias Ringwald 
441b5c1b6b6SMatthias Ringwald #include "btstack_event.h"
442b5c1b6b6SMatthias Ringwald #include "btstack_memory.h"
443905e80caSMatthias Ringwald #include "btstack_run_loop.h"
444905e80caSMatthias Ringwald #include "btstack_run_loop_embedded.h"
445905e80caSMatthias Ringwald #include "hci_dump.h"
446287aaa02SMatthias Ringwald #include "hci_dump_embedded_stdout.h"
447*c8dfe071SMatthias Ringwald #include "hci_transport.h"
448*c8dfe071SMatthias Ringwald #include "hci_transport_em9304_spi.h"
449905e80caSMatthias Ringwald 
450b5c1b6b6SMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
451b5c1b6b6SMatthias Ringwald int btstack_main(int argc, char ** argv);
452b5c1b6b6SMatthias Ringwald 
453b5c1b6b6SMatthias Ringwald // main.c
packet_handler(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)454b5c1b6b6SMatthias Ringwald static void packet_handler (uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
455b5c1b6b6SMatthias Ringwald     UNUSED(size);
456b5c1b6b6SMatthias Ringwald     UNUSED(channel);
457b5c1b6b6SMatthias Ringwald     if (packet_type != HCI_EVENT_PACKET) return;
458b5c1b6b6SMatthias Ringwald     switch(hci_event_packet_get_type(packet)){
459b5c1b6b6SMatthias Ringwald         case BTSTACK_EVENT_STATE:
460b5c1b6b6SMatthias Ringwald             if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) return;
461b5c1b6b6SMatthias Ringwald             printf("BTstack up and running.\n");
462b5c1b6b6SMatthias Ringwald             break;
463b5c1b6b6SMatthias Ringwald         default:
464b5c1b6b6SMatthias Ringwald             break;
465b5c1b6b6SMatthias Ringwald     }
466b5c1b6b6SMatthias Ringwald }
467b5c1b6b6SMatthias Ringwald 
main(void)468905e80caSMatthias Ringwald int main(void)
469905e80caSMatthias Ringwald {
470905e80caSMatthias Ringwald     //
471905e80caSMatthias Ringwald     // Set the clock frequency.
472905e80caSMatthias Ringwald     //
473905e80caSMatthias Ringwald     am_hal_clkgen_sysclk_select(AM_HAL_CLKGEN_SYSCLK_MAX);
474905e80caSMatthias Ringwald 
475905e80caSMatthias Ringwald     //
476905e80caSMatthias Ringwald     // Set the default cache configuration
477905e80caSMatthias Ringwald     //
478905e80caSMatthias Ringwald     am_hal_cachectrl_enable(&am_hal_cachectrl_defaults);
479905e80caSMatthias Ringwald 
480905e80caSMatthias Ringwald     //
481905e80caSMatthias Ringwald     // Configure the board for low power operation.
482905e80caSMatthias Ringwald     //
483905e80caSMatthias Ringwald     am_bsp_low_power_init();
484905e80caSMatthias Ringwald 
485905e80caSMatthias Ringwald     //
486905e80caSMatthias Ringwald     // Initialize the printf interface for UART output.
487905e80caSMatthias Ringwald     //
488905e80caSMatthias Ringwald     am_util_stdio_printf_init((am_util_stdio_print_char_t)am_bsp_uart_string_print);
489905e80caSMatthias Ringwald 
490905e80caSMatthias Ringwald     //
491905e80caSMatthias Ringwald     // Configure and enable the UART.
492905e80caSMatthias Ringwald     //
493905e80caSMatthias Ringwald     uart_init(AM_BSP_UART_PRINT_INST);
494905e80caSMatthias Ringwald 
495905e80caSMatthias Ringwald     //
496905e80caSMatthias Ringwald     // Reboot and configure em9304.
497905e80caSMatthias Ringwald     //
498905e80caSMatthias Ringwald     em9304_init();
499905e80caSMatthias Ringwald 
500905e80caSMatthias Ringwald     am_hal_interrupt_enable(AM_HAL_INTERRUPT_GPIO);
501905e80caSMatthias Ringwald 
502905e80caSMatthias Ringwald     //
503905e80caSMatthias Ringwald     // Enable IOM SPI interrupts.
504905e80caSMatthias Ringwald     //
505905e80caSMatthias Ringwald     am_hal_iom_int_clear(AM_BSP_EM9304_IOM, AM_HAL_IOM_INT_CMDCMP | AM_HAL_IOM_INT_THR);
506905e80caSMatthias Ringwald     am_hal_iom_int_enable(AM_BSP_EM9304_IOM, AM_HAL_IOM_INT_CMDCMP | AM_HAL_IOM_INT_THR);
507905e80caSMatthias Ringwald 
508905e80caSMatthias Ringwald #if (0 == AM_BSP_EM9304_IOM)
509905e80caSMatthias Ringwald       am_hal_interrupt_enable(AM_HAL_INTERRUPT_IOMASTER0);
510905e80caSMatthias Ringwald #elif (5 == AM_BSP_EM9304_IOM)
511905e80caSMatthias Ringwald       am_hal_interrupt_enable(AM_HAL_INTERRUPT_IOMASTER5);
512905e80caSMatthias Ringwald #endif
513905e80caSMatthias Ringwald 
514c5ae0d23SMatthias Ringwald     // Start System Timer (only Apollo 2)
515c5ae0d23SMatthias Ringwald     am_hal_stimer_config(AM_HAL_STIMER_LFRC_1KHZ);
516c5ae0d23SMatthias Ringwald     am_hal_stimer_counter_clear();
517c5ae0d23SMatthias Ringwald 
518905e80caSMatthias Ringwald     // start with BTstack init - especially configure HCI Transport
519905e80caSMatthias Ringwald     btstack_memory_init();
520905e80caSMatthias Ringwald     btstack_run_loop_init(btstack_run_loop_embedded_get_instance());
521905e80caSMatthias Ringwald 
522905e80caSMatthias Ringwald     // init HCI
523905e80caSMatthias Ringwald     hci_init(hci_transport_em9304_spi_instance(btstack_em9304_spi_embedded_instance()), NULL);
524287aaa02SMatthias Ringwald     // hci_dump_init(hci_dump_embedded_stdout_get_instance());
525b5c1b6b6SMatthias Ringwald 
526b5c1b6b6SMatthias Ringwald     // inform about BTstack state
527b5c1b6b6SMatthias Ringwald     hci_event_callback_registration.callback = &packet_handler;
528b5c1b6b6SMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
529905e80caSMatthias Ringwald 
530905e80caSMatthias Ringwald     // hand over control to btstack_main()..
531905e80caSMatthias Ringwald 
532905e80caSMatthias Ringwald     // turn on!
533905e80caSMatthias Ringwald     // hci_power_control(HCI_POWER_ON);
534905e80caSMatthias Ringwald     btstack_main(0, NULL);
535905e80caSMatthias Ringwald 
536905e80caSMatthias Ringwald     btstack_run_loop_execute();
537905e80caSMatthias Ringwald }
538