Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 66 additions & 7 deletions firmware/common/LPC4320_M4_memory.ld
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,75 @@
* Boston, MA 02110-1301, USA.
*/

/* Linker script for HackRF One (LPC4320, 1M SPI flash, 200K SRAM). */
/* Top-level linker script for HackRF One (LPC4320, 1M SPI flash, 200K SRAM). */

/* Depending on the target, the following additional linker scripts are called:
*
* `hackrf_usb.bin`:
* - ${MCU_PARTNO}_M4_memory.ld -> This script
* - LPC43xx_M4_memory.ld -> Defines additional memory regions
* - LPC43xx_M4_M0_image_from_text.ld -> Adds the M0 core's firmware
* - LPC43xx_M4_memory_rom_only.ld -> Adds the fpga bitstreams
* - LPC43xx_M4_rtconfig.ld -> Adds code stored in ram_rtconfig
* - libopencm3_lpc43xx_m0.ld -> Controls linking for M0 code
* - libopencm3_lpc43xx_rom_to_ram.ld -> Controls linking for M4 and shadow region
*
* `hackrf_usb.dfu`:
* - ${MCU_PARTNO}_M4_memory.ld -> This script
* - LPC43xx_M4_memory.ld -> as above
* - LPC43xx_M0_memory.ld -> as above
* - LPC43xx_M4_M0_image_from_text.ld -> as above
* - LPC43xx_M4_rtconfig.ld -> as above
* - libopencm3_lpc43xx.ld -> Controls linking for M4
* - libopencm3_lpc43xx_m0.ld -> as above
*/

MEMORY
{
/* rom is really the shadow region that points to SPI flash or elsewhere */
rom (rx) : ORIGIN = 0x00000000, LENGTH = 1M
ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 64K
ram_usb (rw) : ORIGIN = 0x10010000, LENGTH = 32K
ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 32K
ram_sleep (rwx) : ORIGIN = 0x10088000, LENGTH = 8K
/* UM10503 Rev. 2.5, 10 September 2019
* - Section 3.3.1 Table 10, LPC43xx/LPC43Sxx SRAM configuration
* - Section 3.3.3 On-chip flash
* - Section 3.3.5 Memory retention in the Power-down modes
* - Section 3.4 Figure 8, Flashless parts: Memory map with peripherals
* - Section 5 LPC43xx Boot ROM
* LPC4350/30/20/10 Product data sheet Rev. 4.6, 14 March 2016
* - Section 7.17 Figure 7, LPC4350/30/20/10 Memory mapping (overview)
*/

/* - 0x0000 0000 : 256 MB shadow area ---------------------------------- */
/* The shadow area allows some LPC43xx memory regions to be remapped to
* address 0x0000 0000.
*
* - The default value at RESET is:
* -> Factory boot ROM @ 0x1040 0000
* - Once the boot ROM has initialized SPIFI and established the boot map
* it is re-mapped to our 1M SPI Flash:
* -> SPIFI data @ 0x1400 0000
* - Next, the `.text_ram` region is copied from SPIFI data to `ram_local1`.
* - Finally, execution jumps to `ram_local1` and the firmware begins.
*/
rom (rx) : ORIGIN = 0x00000000, LENGTH = 1M

/* - 0x1000 0000 : 96 kB local SRAM ------------------------------------ */
ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 64K
ram_usb (rw) : ORIGIN = 0x10010000, LENGTH = 32K

/* - 0x1001 8000 : 32 kB local SRAM (LPC4350/30) ----------------------- */
/* - 0x1002 0000 : reserved -------------------------------------------- */

/* - 0x1008 0000 : 32 kB local SRAM (LPC4350/30/20/10) ----------------- */
ram_rtconfig (rx) : ORIGIN = 0x10080000, LENGTH = 16K
ram_local2 (rwx) : ORIGIN = 0x10084000, LENGTH = 16K

/* - 0x1008 8000: 8 kB local SRAM (LPC4320/10) ------------------------- */
ram_sleep (rwx) : ORIGIN = 0x10088000, LENGTH = 8K

/* - 0x1008 A000 : 32 kB local SRAM (LPC4350/30) ----------------------- */
}

ASSERT(
SIZEOF(.text) + SIZEOF(.init_array) + SIZEOF(.ARM.exidx) <= 64K,
"Error: region `ram_local1' exceeds 64 kB."
)

INCLUDE LPC43xx_M4_memory.ld
34 changes: 27 additions & 7 deletions firmware/common/LPC4330_M4_memory.ld
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,36 @@
* Boston, MA 02110-1301, USA.
*/

/* Linker script for Rad1o badge - (LPC4330, 1M SPI flash, 264K SRAM). */
/* Top-level linker script for Rad1o badge (LPC4330, 1M SPI flash, 264K SRAM). */

/* See `LPC4320_M4_memory.ld` for documentation. */

MEMORY
{
/* rom is really the shadow region that points to SPI flash or elsewhere */
rom (rx) : ORIGIN = 0x00000000, LENGTH = 128K
ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 96K
ram_usb(rw) : ORIGIN = 0x10018000, LENGTH = 32K
ram_local2 (rwx) : ORIGIN = 0x10080000, LENGTH = 64K
ram_sleep (rwx) : ORIGIN = 0x10090000, LENGTH = 8K
/* - 0x0000 0000 : 256 MB shadow area ---------------------------------- */
rom (rx) : ORIGIN = 0x00000000, LENGTH = 128K

/* - 0x1000 0000 : 96 kB local SRAM ------------------------------------ */
ram_local1 (rwx) : ORIGIN = 0x10000000, LENGTH = 96K

/* - 0x1001 8000 : 32 kB local SRAM (LPC4350/30) ----------------------- */
ram_usb (rw) : ORIGIN = 0x10018000, LENGTH = 32K

/* - 0x1002 0000 : reserved -------------------------------------------- */

/* - 0x1008 0000 : 32kB local SRAM (LPC4350/30/20/10) ------------------ */
ram_rtconfig (rx) : ORIGIN = 0x10080000, LENGTH = 32K

/* - 0x1008 A000 : 32kB local SRAM (LPC4350/30) ------------------------ */
ram_local2 (rwx) : ORIGIN = 0x1008A000, LENGTH = 32K

/* - 0x1009 0000 : 8kB local SRAM (LPC4350/30) ------------------------ */
ram_sleep (rwx) : ORIGIN = 0x10090000, LENGTH = 8K
}

ASSERT(
SIZEOF(.text) + SIZEOF(.init_array) + SIZEOF(.ARM.exidx) <= 96K,
"Error: region `ram_local1' exceeds 96 kB."
)

INCLUDE LPC43xx_M4_memory.ld
8 changes: 5 additions & 3 deletions firmware/common/LPC43xx_M4_M0_image_from_text.ld
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
SECTIONS
{
.m0_text : {
PROVIDE(__m0_start__ = .);
. = ALIGN(4);
KEEP(*(.m0_bin*));
. = ALIGN(4);
PROVIDE(__m0_end__ = .);
} >rom
} >ram_m0 AT >rom

PROVIDE(__m0_start__ = LOADADDR(.m0_text));
PROVIDE(__m0_end__ = LOADADDR(.m0_text) + SIZEOF(.m0_text));
}
37 changes: 26 additions & 11 deletions firmware/common/LPC43xx_M4_memory.ld
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,40 @@

MEMORY
{
/* Physical address in Flash used to copy Code from Flash to RAM */
rom_flash (rx) : ORIGIN = 0x80000000, LENGTH = 1M
/* UM10503 Rev. 2.5, 10 September 2019
* - Section 3.3.1 Table 10, LPC43xx/LPC43Sxx SRAM configuration
* - Section 3.4 Figure 8, Flashless parts: Memory map with peripherals
* LPC4350/30/20/10 Product data sheet Rev. 4.6, 14 March 2016
* - Section 7.17 Figure 7, LPC4350/30/20/10 Memory mapping (overview)
*/

/* - 0x2000 0000 : 16 kB AHB SRAM (LPC4350/30/20/10) ------------------- */
/* - 0x2000 4000 : 16 kB AHB SRAM (LPC4350/30/20) ---------------------- */
/* Buffers for LZ4 decompression */
ram_lz4_in (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
ram_lz4_out (rwx) : ORIGIN = 0x20001000, LENGTH = 4K
ram_lz4_in (rwx) : ORIGIN = 0x20000000, LENGTH = 4K
ram_lz4_out (rwx) : ORIGIN = 0x20001000, LENGTH = 4K
/* RAM for M0 code */
ram_m0 (rwx) : ORIGIN = 0x20002000, LENGTH = 20K
ram_m0 (rwx) : ORIGIN = 0x20002000, LENGTH = 20K
/* RAM shared between M0 and M4 */
ram_shared (rwx) : ORIGIN = 0x20007000, LENGTH = 4K
/* USB buffer. Straddles two blocks of RAM
* to get performance benefit of having two USB buffers addressable
* simultaneously (on two different buses of the AHB multilayer matrix)
*/
ram_samp (rwx) : ORIGIN = 0x20008000, LENGTH = 32K
ram_shared (rwx) : ORIGIN = 0x20007000, LENGTH = 4K

/* - 0x2000 8000 : 16 kB AHB SRAM (LPC4350/30/20) ---------------------- */
/* - 0x2000 C000 : 16 kB AHB SRAM (LPC4350/30/20/10) ------------------- */
/* USB buffer. Straddles two blocks of RAM to get the performance benefit
* of having two USB buffers addressable simultaneously (on two different
* buses of the AHB multilayer matrix) */
ram_samp (rwx) : ORIGIN = 0x20008000, LENGTH = 32K

/* - 0x8000 0000 : SPIFI data ------------------------------------------ */
/* Physical address in Flash used to copy Code from Flash to RAM */
rom_flash (rx) : ORIGIN = 0x80000000, LENGTH = 1M
}

lz4_in_buf = ORIGIN(ram_lz4_in);
lz4_out_buf = ORIGIN(ram_lz4_out);
usb_samp_buffer = ORIGIN(ram_samp);
usb_bulk_buffer = ORIGIN(ram_usb);
m0_state = ORIGIN(ram_shared);

PROVIDE(__ram_rtconfig_start__ = ORIGIN(ram_rtconfig));
PROVIDE(__ram_m0_start__ = ORIGIN(ram_m0));
32 changes: 32 additions & 0 deletions firmware/common/LPC43xx_M4_rtconfig.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright 2012-2025 Great Scott Gadgets <info@greatscottgadgets.com>
* Copyright 2012 Jared Boone <jared@sharebrained.com>
*
* 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.
*/

SECTIONS
{
.rtconfig_text : {
KEEP(*(.rtconfig));
. = ALIGN(4);
} >ram_rtconfig AT >rom

PROVIDE(__rtconfig_start__ = LOADADDR(.rtconfig_text));
PROVIDE(__rtconfig_end__ = LOADADDR(.rtconfig_text) + SIZEOF(.rtconfig_text));
}
8 changes: 8 additions & 0 deletions firmware/common/fpga.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@

#include "ice40_spi.h"

/* Supported Bitstreams. */
typedef enum {
FPGA_BITSTREAM_STANDARD = 0,
FPGA_BITSTREAM_HALFPREC = 1,
FPGA_BITSTREAM_EXTPREC_RX = 2,
FPGA_BITSTREAM_EXTPREC_TX = 3,
} fpga_bitstream_index_t;

/* Up to 7 registers, each containing up to 8 bits of data */
#define FPGA_NUM_REGS 7
#define FPGA_DATA_REGS_MAX_VALUE 255
Expand Down
1 change: 1 addition & 0 deletions firmware/common/platform_gpio.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

// clang-format off

__attribute__((section(".rtconfig")))
const platform_gpio_t* platform_gpio(void)
{
static const platform_gpio_t* _platform_gpio = NULL;
Expand Down
1 change: 1 addition & 0 deletions firmware/common/platform_scu.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

// clang-format off

__attribute__((section(".rtconfig")))
const platform_scu_t* platform_scu(void)
{
static const platform_scu_t* _platform_scu = NULL;
Expand Down
2 changes: 1 addition & 1 deletion firmware/common/portapack.c
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ bool portapack_present(void)
return portapack_detected;
}

bool portapack_init(void)
__attribute__((section(".rtconfig"))) bool portapack_init(void)
{
if (portapack_detect()) {
portapack_if_init();
Expand Down
91 changes: 91 additions & 0 deletions firmware/common/radio.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,20 +53,27 @@ void radio_init(radio_t* const radio)
radio->config[bank][reg] = RADIO_UNSET;
}
}
radio->config_mode = RADIO_CONFIG_STANDARD;
radio->config[RADIO_BANK_APPLIED][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
radio->config[RADIO_BANK_REQUESTED][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
radio->config[RADIO_BANK_IDLE][RADIO_OPMODE] = TRANSCEIVER_MODE_OFF;
radio->config[RADIO_BANK_RX][RADIO_OPMODE] = TRANSCEIVER_MODE_RX;
radio->config[RADIO_BANK_TX][RADIO_OPMODE] = TRANSCEIVER_MODE_TX;
radio->config[RADIO_BANK_IDLE][RADIO_BIAS_TEE] = false;
radio->regs_dirty = 0;
radio->regs_locked = 0;
}

static inline void mark_dirty(radio_t* const radio, radio_register_t reg)
{
radio->regs_dirty |= (1 << reg);
}

static inline bool check_locked(radio_t* const radio, radio_register_t reg)
{
return radio->regs_locked & (1 << reg);
}

radio_error_t radio_reg_write(
radio_t* const radio,
const radio_register_bank_t bank,
Expand All @@ -77,6 +84,10 @@ radio_error_t radio_reg_write(
return RADIO_ERR_INVALID_REGISTER;
}

if (check_locked(radio, reg)) {
return RADIO_ERR_LOCKED_REGISTER;
}

switch (bank) {
case RADIO_BANK_REQUESTED:
mark_dirty(radio, reg);
Expand Down Expand Up @@ -107,6 +118,20 @@ uint64_t radio_reg_read(
return radio->config[bank][reg];
}

radio_error_t radio_reg_lock(
radio_t* const radio,
const radio_register_t reg,
const bool locked)
{
if (reg > RADIO_NUM_REGS) {
return RADIO_ERR_INVALID_REGISTER;
}

radio->regs_locked = (radio->regs_locked & ~(1 << reg)) | (locked << reg);

return RADIO_OK;
}

static uint32_t radio_update_direction(radio_t* const radio, uint64_t* bank)
{
const uint64_t requested = bank[RADIO_OPMODE];
Expand Down Expand Up @@ -1010,3 +1035,69 @@ void radio_switch_opmode(radio_t* const radio, const transceiver_mode_t mode)
nvic_enable_irq(NVIC_USB0_IRQ);
radio_update(radio);
}

bool radio_set_config_mode(radio_t* const radio, const radio_config_mode_t mode)
{
// Check if the requested mode is supported.
switch (mode) {
case RADIO_CONFIG_STANDARD:
// supported on all boards
break;
#ifdef IS_PRALINE
case RADIO_CONFIG_HALF_PRECISION:
case RADIO_CONFIG_EXT_PRECISION_RX:
case RADIO_CONFIG_EXT_PRECISION_TX:
// only supported on praline
if (!IS_PRALINE) {
return false;
}
break;
#endif
default:
return false;
}

// Don't do anything if we're already in the requested mode.
if (mode == radio->config_mode) {
return true;
}

#if defined(IS_PRALINE) && !(defined(DFU_MODE) || defined(RAM_MODE))
if (IS_PRALINE) {
fpga_bitstream_index_t bitstream_index;
switch (mode) {
case RADIO_CONFIG_STANDARD:
bitstream_index = FPGA_BITSTREAM_STANDARD;
break;
case RADIO_CONFIG_HALF_PRECISION:
bitstream_index = FPGA_BITSTREAM_HALFPREC;
break;
case RADIO_CONFIG_EXT_PRECISION_RX:
bitstream_index = FPGA_BITSTREAM_EXTPREC_RX;
break;
case RADIO_CONFIG_EXT_PRECISION_TX:
bitstream_index = FPGA_BITSTREAM_EXTPREC_TX;
break;
default:
return false;
}

// Reset radio state.
for (uint8_t reg = 0; reg < RADIO_NUM_REGS; reg++) {
radio_reg_write(radio, RADIO_BANK_APPLIED, reg, RADIO_UNSET);
radio_reg_write(radio, RADIO_BANK_REQUESTED, reg, RADIO_UNSET);
}

// Load bitstream.
extern struct fpga_loader_t fpga_loader;
if (!fpga_image_load(&fpga_loader, bitstream_index)) {
return false;
}
}
#endif

// Update radio config mode.
radio->config_mode = mode;

return true;
}
Loading
Loading