Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson 2024-12-12 16:43:03 -08:00 committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions

View file

@ -0,0 +1,116 @@
IRQ_DEF(0, WWDG) // Window WatchDog
IRQ_DEF(1, PVD) // PVD through EXTI Line detection
IRQ_DEF(2, TAMP_STAMP) // Tamper and TimeStamps through the EXTI line
IRQ_DEF(3, RTC_WKUP) // RTC Wakeup through the EXTI line
IRQ_DEF(4, FLASH) // FLASH
IRQ_DEF(5, RCC) // RCC
IRQ_DEF(6, EXTI0) // EXTI Line0
IRQ_DEF(7, EXTI1) // EXTI Line1
IRQ_DEF(8, EXTI2) // EXTI Line2
IRQ_DEF(9, EXTI3) // EXTI Line3
IRQ_DEF(10, EXTI4) // EXTI Line4
IRQ_DEF(11, DMA1_Stream0) // DMA1 Stream 0
IRQ_DEF(12, DMA1_Stream1) // DMA1 Stream 1
IRQ_DEF(13, DMA1_Stream2) // DMA1 Stream 2
IRQ_DEF(14, DMA1_Stream3) // DMA1 Stream 3
IRQ_DEF(15, DMA1_Stream4) // DMA1 Stream 4
IRQ_DEF(16, DMA1_Stream5) // DMA1 Stream 5
IRQ_DEF(17, DMA1_Stream6) // DMA1 Stream 6
IRQ_DEF(18, ADC) // ADC1, ADC2 and ADC3s
IRQ_DEF(19, CAN1_TX) // CAN1 TX
IRQ_DEF(20, CAN1_RX0) // CAN1 RX0
IRQ_DEF(21, CAN1_RX1) // CAN1 RX1
IRQ_DEF(22, CAN1_SCE) // CAN1 SCE
IRQ_DEF(23, EXTI9_5) // External Line[9:5]s
IRQ_DEF(24, TIM1_BRK_TIM9) // TIM1 Break and TIM9
IRQ_DEF(25, TIM1_UP_TIM10) // TIM1 Update and TIM10
IRQ_DEF(26, TIM1_TRG_COM_TIM11) // TIM1 Trigger and Commutation and TIM11
IRQ_DEF(27, TIM1_CC) // TIM1 Capture Compare
IRQ_DEF(28, TIM2) // TIM2
IRQ_DEF(29, TIM3) // TIM3
IRQ_DEF(30, TIM4) // TIM4
IRQ_DEF(31, I2C1_EV) // I2C1 Event
IRQ_DEF(32, I2C1_ER) // I2C1 Error
IRQ_DEF(33, I2C2_EV) // I2C2 Event
IRQ_DEF(34, I2C2_ER) // I2C2 Error
IRQ_DEF(35, SPI1) // SPI1
IRQ_DEF(36, SPI2) // SPI2
IRQ_DEF(37, USART1) // USART1
IRQ_DEF(38, USART2) // USART2
IRQ_DEF(39, USART3) // USART3
IRQ_DEF(40, EXTI15_10) // External Line[15:10]s
IRQ_DEF(41, RTC_Alarm) // RTC Alarm (A and B) through EXTI Line
IRQ_DEF(42, OTG_FS_WKUP) // USB OTG FS Wakeup through EXTI line
IRQ_DEF(43, TIM8_BRK_TIM12) // TIM8 Break and TIM12
IRQ_DEF(44, TIM8_UP_TIM13) // TIM8 Update and TIM13
IRQ_DEF(45, TIM8_TRG_COM_TIM14) // TIM8 Trigger and Commutation and TIM14
IRQ_DEF(46, TIM8_CC) // TIM8 Capture Compare
IRQ_DEF(47, DMA1_Stream7) // DMA1 Stream7
IRQ_DEF(48, FSMC) // FSMC
IRQ_DEF(49, SDIO) // SDIO
IRQ_DEF(50, TIM5) // TIM5
IRQ_DEF(51, SPI3) // SPI3
#if !defined(STM32F412xG)
IRQ_DEF(52, UART4) // UART4
IRQ_DEF(53, UART5) // UART5
IRQ_DEF(54, TIM6_DAC) // TIM6 and DAC1&2 underrun errors
#else
IRQ_DEF(54, TIM6) // TIM6
#endif
IRQ_DEF(55, TIM7) // TIM7
IRQ_DEF(56, DMA2_Stream0) // DMA2 Stream 0
IRQ_DEF(57, DMA2_Stream1) // DMA2 Stream 1
IRQ_DEF(58, DMA2_Stream2) // DMA2 Stream 2
IRQ_DEF(59, DMA2_Stream3) // DMA2 Stream 3
IRQ_DEF(60, DMA2_Stream4) // DMA2 Stream 4
#if !defined(STM32F412xG)
IRQ_DEF(61, ETH) // Ethernet
IRQ_DEF(62, ETH_WKUP) // Ethernet Wakeup through EXTI line
#else
IRQ_DEF(61, DFSDM1) // DFSDM1
IRQ_DEF(62, DFSDM2) // DFSDM2
#endif
IRQ_DEF(63, CAN2_TX) // CAN2 TX
IRQ_DEF(64, CAN2_RX0) // CAN2 RX0
IRQ_DEF(65, CAN2_RX1) // CAN2 RX1
IRQ_DEF(66, CAN2_SCE) // CAN2 SCE
IRQ_DEF(67, OTG_FS) // USB OTG FS
IRQ_DEF(68, DMA2_Stream5) // DMA2 Stream 5
IRQ_DEF(69, DMA2_Stream6) // DMA2 Stream 6
IRQ_DEF(70, DMA2_Stream7) // DMA2 Stream 7
IRQ_DEF(71, USART6) // USART6
IRQ_DEF(72, I2C3_EV) // I2C3 event
IRQ_DEF(73, I2C3_ER) // I2C3 error
#if !defined(STM32F412xG)
IRQ_DEF(74, OTG_HS_EP1_OUT) // USB OTG HS End Point 1 Out
IRQ_DEF(75, OTG_HS_EP1_IN) // USB OTG HS End Point 1 In
IRQ_DEF(76, OTG_HS_WKUP) // USB OTG HS Wakeup through EXTI
IRQ_DEF(77, OTG_HS) // USB OTG HS
IRQ_DEF(78, DCMI) // DCMI
IRQ_DEF(79, CRYP) // CRYP crypto
#endif
#if !defined(STM32F412xG)
IRQ_DEF(80, HASH_RNG) // Hash and Rng
#else
IRQ_DEF(80, RNG) // Rng
#endif
#if !defined(STM32F2XX) // STM32F2 IRQs end here
IRQ_DEF(81, FPU) // FPU
#if !defined(STM32F412xG)
IRQ_DEF(82, UART7) // UART7
IRQ_DEF(83, UART8) // UART8
#endif
IRQ_DEF(84, SPI4) // SPI4
IRQ_DEF(85, SPI5) // SPI5
#if !defined(STM32F412xG)
IRQ_DEF(86, SPI6) // SPI6
IRQ_DEF(87, SAI1) // SAI1
IRQ_DEF(88, LTDC) // LTDC
IRQ_DEF(89, LTDC_ER) // LTDC_ER
IRQ_DEF(90, DMA2D) // DMA2D
#else
IRQ_DEF(92, QUADSPI) // QUADSPI
IRQ_DEF(95, FMPI2C1_EV) // FMPI2C1 Event
IRQ_DEF(96, FMPI2C1_ER) // FMPI2C1 Error
#endif
#endif // !defined(STM32F2XX)

View file

@ -0,0 +1,112 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdint.h>
#define HEADER_ADDR (0x20000400)
#define DATA_ADDR (0x20000800)
#define FLASH_SR_ADDR (0x40023C0C)
#define STATE_WAITING (0)
#define STATE_WRITE (1)
#define STATE_CRC (2)
// typedef to make it easy to change the program size
typedef uint8_t p_size_t;
typedef struct __attribute__((__packed__)) {
uint32_t state;
volatile p_size_t *addr;
uint32_t length;
} Header;
static uint8_t prv_crc8(const uint8_t *data, uint32_t data_len) {
uint8_t crc = 0;
// nibble lookup table for (x^8 + x^5 + x^3 + x^2 + x + 1)
static const uint8_t lookup_table[] =
{ 0, 47, 94, 113, 188, 147, 226, 205, 87, 120, 9, 38, 235, 196, 181, 154 };
for (uint32_t i = 0; i < data_len * 2; i++) {
uint8_t nibble = data[i / 2];
if (i % 2 == 0) {
nibble >>= 4;
}
uint8_t index = nibble ^ (crc >> 4);
crc = lookup_table[index & 0xf] ^ ((crc << 4) & 0xf0);
}
return crc;
}
static void prv_wait_for_flash_not_busy(void) {
while ((*(volatile uint32_t *)FLASH_SR_ADDR) & (1 << 16)); // BSY flag in FLASH_SR
}
__attribute__((__noreturn__)) void Reset_Handler(void) {
// Disable all interrupts
__asm__("cpsid i" : : : "memory");
volatile uint32_t *flash_sr = (volatile uint32_t *)FLASH_SR_ADDR;
volatile p_size_t *data = (volatile p_size_t *)DATA_ADDR;
volatile Header *header = (volatile Header *)HEADER_ADDR;
header->state = STATE_WAITING;
while(1) {
switch (header->state) {
case STATE_WRITE:
prv_wait_for_flash_not_busy();
for (uint32_t i = 0; i < header->length / sizeof(p_size_t); i++) {
header->addr[i] = data[i];
__asm__("isb 0xF":::"memory");
__asm__("dsb 0xF":::"memory");
/// Wait until flash isn't busy
prv_wait_for_flash_not_busy();
if (*flash_sr & (0x1f << 4)) {
// error raised, set bad state
header->state = *flash_sr;
}
if (header->addr[i] != data[i]) {
header->state = 0xbd;
}
}
header->addr += header->length / sizeof(p_size_t);
header->state = STATE_WAITING;
break;
case STATE_CRC:
*data = prv_crc8((uint8_t *)header->addr, header->length);
header->state = STATE_WAITING;
break;
default:
break;
}
}
__builtin_unreachable();
}
//! These symbols are defined in the linker script for use in initializing
//! the data sections. uint8_t since we do arithmetic with section lengths.
//! These are arrays to avoid the need for an & when dealing with linker symbols.
extern uint8_t _estack[];
__attribute__((__section__(".isr_vector"))) const void * const vector_table[] = {
_estack,
Reset_Handler
};

View file

@ -0,0 +1,136 @@
__Stack_Size = 128;
PROVIDE ( _Stack_Size = __Stack_Size ) ;
__Stack_Init = _estack - __Stack_Size ;
PROVIDE ( _Stack_Init = __Stack_Init ) ;
MEMORY
{
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 1K
}
SECTIONS
{
/* for Cortex devices, the beginning of the startup code is stored in the .isr_vector section, which goes to FLASH */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >RAM
/* for some STRx devices, the beginning of the startup code is stored in the .flashtext section, which goes to FLASH */
.flashtext :
{
. = ALIGN(4);
*(.flashtext) /* Startup code */
. = ALIGN(4);
} >RAM
/* Exception handling sections. "contains index entries for section unwinding" */
.ARM.exidx :
{
. = ALIGN(4);
*(.ARM.exidx)
. = ALIGN(4);
} >RAM
/* the program code is stored in the .text section, which goes to Flash */
.text :
{
. = ALIGN(4);
*(.text) /* remaining code */
*(.text.*) /* remaining code */
*(.rodata) /* read-only data (constants) */
*(.rodata*)
*(.constdata) /* read-only data (constants) */
*(.constdata*)
*(.glue_7)
*(.glue_7t)
*(i.*)
. = ALIGN(4);
} >RAM
/* This is the initialized data section
The program executes knowing that the data is in the RAM
but the loader puts the initial values in the FLASH (inidata).
It is one task of the startup to copy the initial values from FLASH to RAM. */
.data : {
. = ALIGN(4);
/* This is used by the startup in order to initialize the .data secion */
__data_start = .;
*(.data)
*(.data.*)
. = ALIGN(4);
__data_end = .; /* This is used by the startup in order to initialize the .data secion */
} >RAM
__data_load_start = LOADADDR(.data);
/* This is the uninitialized data section */
.bss (NOLOAD) : {
. = ALIGN(4);
__bss_start = .; /* This is used by the startup in order to initialize the .bss secion */
*(.bss)
*(.bss.*)
*(COMMON)
. = ALIGN(4);
__bss_end = .; /* This is used by the startup in order to initialize the .bss secion */
} >RAM
.stack (NOLOAD) : {
. = ALIGN(8);
_sstack = .;
. = . + __Stack_Size;
. = ALIGN(8);
_estack = .;
} >RAM
/* after that it's only debugging information. */
/* remove the debugging information from the standard libraries */
DISCARD : {
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
}

View file

@ -0,0 +1,29 @@
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from waflib import Utils, Errors
from waflib.TaskGen import after, feature
@after('apply_link')
@feature('cprogram', 'cshlib')
def process_ldscript(self):
if not getattr(self, 'ldscript', None) or self.env.CC_NAME != 'gcc':
return
node = self.path.find_resource(self.ldscript)
if not node:
raise Errors.WafError('could not find %r' % self.ldscript)
self.link_task.env.append_value('LINKFLAGS', '-T%s' % node.abspath())
self.link_task.dep_nodes.append(node)

View file

@ -0,0 +1,84 @@
#!/usr/bin/python
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Grygoriy Fuchedzhy 2010
"""
Support for converting linked targets to ihex, srec or binary files using
objcopy. Use the 'objcopy' feature in conjuction with the 'cc' or 'cxx'
feature. The 'objcopy' feature uses the following attributes:
objcopy_bfdname Target object format name (eg. ihex, srec, binary).
Defaults to ihex.
objcopy_target File name used for objcopy output. This defaults to the
target name with objcopy_bfdname as extension.
objcopy_install_path Install path for objcopy_target file. Defaults to ${PREFIX}/fw.
objcopy_flags Additional flags passed to objcopy.
"""
from waflib.Utils import def_attrs
from waflib import Task
from waflib.TaskGen import feature, after_method
class objcopy(Task.Task):
run_str = '${OBJCOPY} -O ${TARGET_BFDNAME} ${OBJCOPYFLAGS} ${SRC} ${TGT}'
color = 'CYAN'
@feature('objcopy')
@after_method('apply_link')
def objcopy(self):
def_attrs(self,
objcopy_bfdname='ihex',
objcopy_target=None,
objcopy_install_path="${PREFIX}/firmware",
objcopy_flags='')
link_output = self.link_task.outputs[0]
if not self.objcopy_target:
self.objcopy_target = link_output.change_ext('.' + self.objcopy_bfdname).name
elif isinstance(self.objcopy_target, str):
self.objcopy_target = self.path.find_or_declare(self.objcopy_target)
task = self.create_task('objcopy',
src=link_output,
tgt=self.objcopy_target)
task.env.append_unique('TARGET_BFDNAME', self.objcopy_bfdname)
try:
task.env.append_unique('OBJCOPYFLAGS', getattr(self, 'objcopy_flags'))
except AttributeError:
pass
if self.objcopy_install_path:
self.bld.install_files(self.objcopy_install_path,
task.outputs[0],
env=task.env.derive())
def configure(ctx):
objcopy = ctx.find_program('objcopy', var='OBJCOPY', mandatory=True)
def objcopy_simple(task, mode):
return task.exec_command('arm-none-eabi-objcopy -S -R .stack -R .priv_bss'
' -R .bss -O %s "%s" "%s"' %
(mode, task.inputs[0].abspath(), task.outputs[0].abspath()))
def objcopy_simple_bin(task):
return objcopy_simple(task, 'binary')

View file

@ -0,0 +1,63 @@
# Build script for the silk loader
import sys
import os
from waflib import Logs
def options(opt):
opt.load('gcc')
def configure(conf):
# Find our binary tools
conf.find_program('arm-none-eabi-gcc', var='CC', mandatory=True)
conf.env.AS = conf.env.CC
conf.find_program('arm-none-eabi-gcc-ar', var='AR', mandatory=True)
conf.load('gcc')
for tool in 'ar objcopy'.split():
conf.find_program('arm-none-eabi-' + tool, var=tool.upper(), mandatory=True)
# Set up our compiler configuration
CPU_FLAGS = ['-mcpu=cortex-m3', '-mthumb']
OPT_FLAGS = ['-Os', '-g']
C_FLAGS = [
'-std=c11', '-ffunction-sections',
'-Wall', '-Wextra', '-Werror', '-Wpointer-arith',
'-Wno-unused-parameter', '-Wno-missing-field-initializers',
'-Wno-error=unused-function', '-Wno-error=unused-variable',
'-Wno-error=unused-parameter', '-Wno-error=unused-but-set-variable',
'-Wno-packed-bitfield-compat'
]
LINK_FLAGS = ['-Wl,--gc-sections', '-specs=nano.specs']
conf.env.append_unique('CFLAGS', CPU_FLAGS + OPT_FLAGS + C_FLAGS)
conf.env.append_unique('LINKFLAGS', LINK_FLAGS + CPU_FLAGS + OPT_FLAGS)
conf.env.append_unique('DEFINES', ['_REENT_SMALL=1'])
# Load up other waftools that we need
conf.load('objcopy ldscript', tooldir='waftools')
def build(bld):
elf_node = bld.path.get_bld().make_node('loader.elf')
linkflags = ['-Wl,-Map,loader.map']
sources = ['src/**/*.c']
includes = ['src']
bld.program(features="objcopy",
source=bld.path.ant_glob(sources),
includes=includes,
target=elf_node,
ldscript='src/stm32f4_loader.ld',
linkflags=linkflags,
objcopy_bfdname='ihex',
objcopy_target=elf_node.change_ext('.hex'))
import objcopy
bld(rule=objcopy.objcopy_simple_bin, source='loader.elf', target='loader.bin')
# vim:filetype=python