diff --git a/firmware/common/LPC43xx_M4_memory.ld b/firmware/common/LPC43xx_M4_memory.ld index 71e78216..6d501e3c 100644 --- a/firmware/common/LPC43xx_M4_memory.ld +++ b/firmware/common/LPC43xx_M4_memory.ld @@ -34,3 +34,6 @@ MEMORY } usb_bulk_buffer = ORIGIN(ram_usb); +usb_bulk_buffer_offset = ORIGIN(ram_shared); +usb_bulk_buffer_tx = ORIGIN(ram_shared)+4; +PROVIDE(__ram_m0_start__ = ORIGIN(ram_m0)); diff --git a/firmware/common/streaming.c b/firmware/common/streaming.c index 61105f76..01831a4f 100644 --- a/firmware/common/streaming.c +++ b/firmware/common/streaming.c @@ -26,8 +26,6 @@ #include void baseband_streaming_enable(sgpio_config_t* const sgpio_config) { - nvic_set_priority(NVIC_SGPIO_IRQ, 0); - nvic_enable_irq(NVIC_SGPIO_IRQ); SGPIO_SET_EN_1 = (1 << SGPIO_SLICE_A); sgpio_cpld_stream_enable(sgpio_config); @@ -35,6 +33,4 @@ void baseband_streaming_enable(sgpio_config_t* const sgpio_config) { void baseband_streaming_disable(sgpio_config_t* const sgpio_config) { sgpio_cpld_stream_disable(sgpio_config); - - nvic_disable_irq(NVIC_SGPIO_IRQ); } diff --git a/firmware/hackrf_usb/CMakeLists.txt b/firmware/hackrf_usb/CMakeLists.txt index 7e124b1f..e97968a0 100644 --- a/firmware/hackrf_usb/CMakeLists.txt +++ b/firmware/hackrf_usb/CMakeLists.txt @@ -35,7 +35,6 @@ set(SRC_M4 hackrf_usb.c "${PATH_HACKRF_FIRMWARE_COMMON}/tuning.c" "${PATH_HACKRF_FIRMWARE_COMMON}/streaming.c" - sgpio_isr.c usb_bulk_buffer.c "${PATH_HACKRF_FIRMWARE_COMMON}/usb.c" "${PATH_HACKRF_FIRMWARE_COMMON}/usb_request.c" @@ -63,6 +62,8 @@ set(SRC_M4 "${PATH_HACKRF_FIRMWARE_COMMON}/operacake.c" ) +set(SRC_M0 sgpio_m0.s) + if(BOARD STREQUAL "HACKRF_ONE") SET(SRC_M4 ${SRC_M4} diff --git a/firmware/hackrf_usb/hackrf_usb.c b/firmware/hackrf_usb/hackrf_usb.c index 2498c9fb..195250a2 100644 --- a/firmware/hackrf_usb/hackrf_usb.c +++ b/firmware/hackrf_usb/hackrf_usb.c @@ -22,7 +22,9 @@ #include +#include #include +#include #include @@ -50,6 +52,10 @@ #include "hackrf-ui.h" +extern uint32_t __m0_start__; +extern uint32_t __m0_end__; +extern uint32_t __ram_m0_start__; + static usb_request_handler_fn vendor_request_handler[] = { NULL, usb_vendor_request_set_transceiver_mode, @@ -176,6 +182,16 @@ static bool cpld_jtag_sram_load(jtag_t* const jtag) { return success; } +static void m0_rom_to_ram() { + uint32_t *dest = &__ram_m0_start__; + uint32_t *src = &__m0_start__; + while (src < &__m0_end__) { + *dest = *src; + dest++; + src++; + } +} + int main(void) { bool operacake_allow_gpio; pin_setup(); @@ -188,6 +204,10 @@ int main(void) { #endif cpu_clock_init(); + /* Wake the M0 */ + m0_rom_to_ram(); + ipc_start_m0((uint32_t)&__ram_m0_start__); + if( !cpld_jtag_sram_load(&jtag_cpld) ) { halt_and_flash(6000000); } @@ -229,6 +249,7 @@ int main(void) { operacake_init(operacake_allow_gpio); unsigned int phase = 0; + usb_bulk_buffer_offset = 0; while(true) { // Check whether we need to initiate a CPLD update diff --git a/firmware/hackrf_usb/sgpio_isr.c b/firmware/hackrf_usb/sgpio_isr.c deleted file mode 100644 index e4ed539a..00000000 --- a/firmware/hackrf_usb/sgpio_isr.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2012 Jared Boone - * Copyright 2013 Benjamin Vernoux - * - * This file is part of HackRF. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "sgpio_isr.h" - -#include - -#include "usb_bulk_buffer.h" - -void sgpio_isr_rx() { - SGPIO_CLR_STATUS_1 = (1 << SGPIO_SLICE_A); - - uint32_t* const p = (uint32_t*)&usb_bulk_buffer[usb_bulk_buffer_offset]; - __asm__( - "ldr r0, [%[SGPIO_REG_SS], #44]\n\t" - "str r0, [%[p], #0]\n\t" - "ldr r0, [%[SGPIO_REG_SS], #20]\n\t" - "str r0, [%[p], #4]\n\t" - "ldr r0, [%[SGPIO_REG_SS], #40]\n\t" - "str r0, [%[p], #8]\n\t" - "ldr r0, [%[SGPIO_REG_SS], #8]\n\t" - "str r0, [%[p], #12]\n\t" - "ldr r0, [%[SGPIO_REG_SS], #36]\n\t" - "str r0, [%[p], #16]\n\t" - "ldr r0, [%[SGPIO_REG_SS], #16]\n\t" - "str r0, [%[p], #20]\n\t" - "ldr r0, [%[SGPIO_REG_SS], #32]\n\t" - "str r0, [%[p], #24]\n\t" - "ldr r0, [%[SGPIO_REG_SS], #0]\n\t" - "str r0, [%[p], #28]\n\t" - : - : [SGPIO_REG_SS] "l" (SGPIO_PORT_BASE + 0x100), - [p] "l" (p) - : "r0" - ); - usb_bulk_buffer_offset = (usb_bulk_buffer_offset + 32) & usb_bulk_buffer_mask; -} - -void sgpio_isr_tx() { - SGPIO_CLR_STATUS_1 = (1 << SGPIO_SLICE_A); - - uint32_t* const p = (uint32_t*)&usb_bulk_buffer[usb_bulk_buffer_offset]; - __asm__( - "ldr r0, [%[p], #0]\n\t" - "str r0, [%[SGPIO_REG_SS], #44]\n\t" - "ldr r0, [%[p], #4]\n\t" - "str r0, [%[SGPIO_REG_SS], #20]\n\t" - "ldr r0, [%[p], #8]\n\t" - "str r0, [%[SGPIO_REG_SS], #40]\n\t" - "ldr r0, [%[p], #12]\n\t" - "str r0, [%[SGPIO_REG_SS], #8]\n\t" - "ldr r0, [%[p], #16]\n\t" - "str r0, [%[SGPIO_REG_SS], #36]\n\t" - "ldr r0, [%[p], #20]\n\t" - "str r0, [%[SGPIO_REG_SS], #16]\n\t" - "ldr r0, [%[p], #24]\n\t" - "str r0, [%[SGPIO_REG_SS], #32]\n\t" - "ldr r0, [%[p], #28]\n\t" - "str r0, [%[SGPIO_REG_SS], #0]\n\t" - : - : [SGPIO_REG_SS] "l" (SGPIO_PORT_BASE + 0x100), - [p] "l" (p) - : "r0" - ); - usb_bulk_buffer_offset = (usb_bulk_buffer_offset + 32) & usb_bulk_buffer_mask; -} diff --git a/firmware/hackrf_usb/sgpio_isr.h b/firmware/hackrf_usb/sgpio_isr.h deleted file mode 100644 index 31162440..00000000 --- a/firmware/hackrf_usb/sgpio_isr.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2012 Jared Boone - * Copyright 2013 Benjamin Vernoux - * - * This file is part of HackRF. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __SGPIO_ISR_H__ -#define __SGPIO_ISR_H__ - -void sgpio_isr_rx(); -void sgpio_isr_tx(); - -#endif/*__SGPIO_ISR_H__*/ diff --git a/firmware/hackrf_usb/sgpio_m0.s b/firmware/hackrf_usb/sgpio_m0.s new file mode 100644 index 00000000..9bbca574 --- /dev/null +++ b/firmware/hackrf_usb/sgpio_m0.s @@ -0,0 +1,108 @@ +/* + * This file is part of GreatFET + * + * Specialized SGPIO interrupt handler for Rhododendron. + */ + + +// Constants that point to registers we'll need to modify in the SGPIO block. +.equ SGPIO_REGISTER_BLOCK_BASE, 0x40101000 +.equ SGPIO_SHADOW_REGISTERS_BASE, 0x40101100 +.equ SGPIO_EXCHANGE_INTERRUPT_CLEAR_REG, 0x40101F30 +.equ SGPIO_EXCHANGE_INTERRUPT_STATUS_REG, 0x40101F2C +.equ SGPIO_GPIO_INPUT, 0x40101210 + + +// Buffer that we're funneling data to/from. +.equ TARGET_DATA_BUFFER, 0x20008000 +.equ TARGET_BUFFER_POSITION, 0x20007000 +.equ TARGET_BUFFER_TX, 0x20007004 +.equ TARGET_BUFFER_MASK, 0x7fff + +.global main +.thumb_func +main: + + // Spin until we're ready to handle an SGPIO packet: + // Grab the exchange interrupt staus... + ldr r0, =SGPIO_EXCHANGE_INTERRUPT_STATUS_REG + ldr r0, [r0] + + // ... check to see if it has any interrupt bits set... + lsr r0, #1 + + // ... and if not, jump back to the beginning. + bcc main + + // Clear the interrupt pending bits for the SGPIO slices we're working with. + ldr r0, =SGPIO_EXCHANGE_INTERRUPT_CLEAR_REG + ldr r1, =0xffff + str r1, [r0] + + // Grab the base address of the SGPIO shadow registers... + ldr r7, =SGPIO_SHADOW_REGISTERS_BASE + + // ... and grab the address of the buffer segment we want to write to / read from. + ldr r0, =TARGET_DATA_BUFFER // r0 = &buffer + ldr r3, =TARGET_BUFFER_POSITION // r3 = &position_in_buffer + ldr r2, [r3] // r2 = position_in_buffer + add r6, r0, r2 // r6 = buffer_target = &buffer + position_in_buffer + + mov r8, r3 // Store &position_in_buffer. + + // Our slice chain is set up as follows (ascending data age; arrows are reversed for flow): + // L -> F -> K -> C -> J -> E -> I -> A + // Which has equivalent shadow register offsets: + // 44 -> 20 -> 40 -> 8 -> 36 -> 16 -> 32 -> 0 + + // Load direction (TX or RX) + ldr r0, =TARGET_BUFFER_TX + ldr r0, [r0] + + // TX? + lsr r0, #1 + bcc direction_rx + +direction_tx: + + ldm r6!, {r0-r5} + str r0, [r7, #44] + str r1, [r7, #20] + str r2, [r7, #40] + str r3, [r7, #8 ] + str r4, [r7, #36] + str r5, [r7, #16] + + ldm r6!, {r0-r1} + str r0, [r7, #32] + str r1, [r7, #0] + + b done + +direction_rx: + + // 8 cycles + ldr r0, [r7, #44] // 2 + ldr r1, [r7, #20] // 2 + ldr r2, [r7, #40] // 2 + ldr r3, [r7, #8 ] // 2 + ldr r4, [r7, #36] // 2 + ldr r5, [r7, #16] // 2 + stm r6!, {r0-r5} // 7 + + // 6 cycles + ldr r0, [r7, #32] // 2 + ldr r1, [r7, #0] // 2 + stm r6!, {r0-r1} + +done: + + // Finally, update the buffer location... + ldr r0, =TARGET_BUFFER_MASK + and r0, r6, r0 // r0 = (position_in_buffer + size_copied) % buffer_size + + // ... restore &position_in_buffer, and store the new position there... + mov r1, r8 + str r0, [r1] // position_in_buffer = (position_in_buffer + size_copied) % buffer_size + + b main diff --git a/firmware/hackrf_usb/usb_api_transceiver.c b/firmware/hackrf_usb/usb_api_transceiver.c index 3d64d7f9..86c044d4 100644 --- a/firmware/hackrf_usb/usb_api_transceiver.c +++ b/firmware/hackrf_usb/usb_api_transceiver.c @@ -24,8 +24,7 @@ #include "hackrf-ui.h" #include -#include -#include "sgpio_isr.h" +#include "usb_bulk_buffer.h" #include "usb_api_cpld.h" // Remove when CPLD update is handled elsewhere @@ -257,18 +256,18 @@ void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode) { led_on(LED2); usb_endpoint_init(&usb_endpoint_bulk_in); rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_RX); - vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx; + usb_bulk_buffer_tx = false; } else if (_transceiver_mode == TRANSCEIVER_MODE_TX) { led_off(LED2); led_on(LED3); usb_endpoint_init(&usb_endpoint_bulk_out); rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_TX); - vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_tx; + usb_bulk_buffer_tx = true; } else { led_off(LED2); led_off(LED3); rf_path_set_direction(&rf_path, RF_PATH_DIRECTION_OFF); - vector_table.irq[NVIC_SGPIO_IRQ] = sgpio_isr_rx; + usb_bulk_buffer_tx = false; } diff --git a/firmware/hackrf_usb/usb_bulk_buffer.c b/firmware/hackrf_usb/usb_bulk_buffer.c index 9b671e05..ea3e6b77 100644 --- a/firmware/hackrf_usb/usb_bulk_buffer.c +++ b/firmware/hackrf_usb/usb_bulk_buffer.c @@ -22,5 +22,4 @@ #include "usb_bulk_buffer.h" -const uint32_t usb_bulk_buffer_mask = 32768 - 1; volatile uint32_t usb_bulk_buffer_offset = 0; diff --git a/firmware/hackrf_usb/usb_bulk_buffer.h b/firmware/hackrf_usb/usb_bulk_buffer.h index 2acce718..0900fd4d 100644 --- a/firmware/hackrf_usb/usb_bulk_buffer.h +++ b/firmware/hackrf_usb/usb_bulk_buffer.h @@ -23,6 +23,7 @@ #ifndef __USB_BULK_BUFFER_H__ #define __USB_BULK_BUFFER_H__ +#include #include /* Address of usb_bulk_buffer is set in ldscripts. If you change the name of this @@ -31,8 +32,8 @@ */ extern uint8_t usb_bulk_buffer[32768]; -extern const uint32_t usb_bulk_buffer_mask; - extern volatile uint32_t usb_bulk_buffer_offset; +extern bool usb_bulk_buffer_tx; + #endif/*__USB_BULK_BUFFER_H__*/