aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/i2c1/CMakeLists.txt29
-rw-r--r--apps/i2c1/i2c1.cpp355
-rw-r--r--cmake/stm32.toolchain.cmake9
-rw-r--r--gdb-apps207
-rw-r--r--gdb-start143
-rw-r--r--html/module.pngbin0 -> 816309 bytes
-rw-r--r--html/pinout-2.html519
-rw-r--r--html/pinout.html682
-rw-r--r--html/tables.html80
-rw-r--r--playground/include/playground.h29
-rw-r--r--playground/include/stm32f10x_conf.h6
11 files changed, 1911 insertions, 148 deletions
diff --git a/apps/i2c1/CMakeLists.txt b/apps/i2c1/CMakeLists.txt
new file mode 100644
index 0000000..67139f8
--- /dev/null
+++ b/apps/i2c1/CMakeLists.txt
@@ -0,0 +1,29 @@
+add_executable(i2c1.elf i2c1.cpp
+ ${PLAYGROUND_DIR}/src/init_low.s ${PLAYGROUND_DIR}/src/init_high.cpp ${PLAYGROUND_DIR}/include/init_high.h
+ ${PLAYGROUND_DIR}/include/playground.h
+ ${PLAYGROUND_DIR}/src/debug.cpp ${PLAYGROUND_DIR}/include/debug.h
+ ${PLAYGROUND_DIR}/include/stm32f10x_conf.h
+ # http://www.sparetimelabs.com/tinyprintf/tinyprintf.php
+ ${TINYPRINTF_DIR}/tinyprintf.c ${TINYPRINTF_DIR}/tinyprintf.h
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/CMSIS/CM3/CoreSupport/core_cm3.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x/system_stm32f10x.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_rcc.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_gpio.c
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/src/stm32f10x_i2c.c
+ )
+
+target_include_directories(i2c1.elf PUBLIC
+ ${PLAYGROUND_DIR}/include
+ ${TINYPRINTF_DIR}
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/CMSIS/CM3/CoreSupport
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/CMSIS/CM3/DeviceSupport/ST/STM32F10x
+ ${STM32F10X_STDPERIPH_LIB}/Libraries/STM32F10x_StdPeriph_Driver/inc)
+target_compile_definitions(i2c1.elf PUBLIC ${STM32F10X_STDPERIPH_DEFINES} USE_FULL_ASSERT)
+
+set_target_properties(i2c1.elf PROPERTIES O_LEVEL 3)
+
+#set_source_files_properties(i2c1.cpp PROPERTIES O_LEVEL s)
+set_property(SOURCE i2c1.cpp APPEND_STRING PROPERTY COMPILE_FLAGS "-O0")
+
+set_target_properties(i2c1.elf PROPERTIES LINK_FLAGS "-nostartfiles -T${CMAKE_SOURCE_DIR}/cmake/stm32.ld")
+add_extra_commands(i2c1.elf)
diff --git a/apps/i2c1/i2c1.cpp b/apps/i2c1/i2c1.cpp
new file mode 100644
index 0000000..b6d0a27
--- /dev/null
+++ b/apps/i2c1/i2c1.cpp
@@ -0,0 +1,355 @@
+#include <cstdint>
+#include <cstring>
+#include <stm32f10x_conf.h>
+#include <stm32f10x.h>
+#include <stm32f10x_rcc.h>
+#include <stm32f10x_gpio.h>
+#include <stm32f10x_i2c.h>
+#include <inttypes.h>
+#include <playground.h>
+#include "debug.h"
+#include "tinyprintf.h"
+
+extern "C" void halt();
+
+extern "C"
+__attribute__((naked))
+void HardFault_Handler_C(uint32_t *hardfault_args) {
+ dbg_printf("r0 = 0x%08lx (%lu)\n", hardfault_args[0], hardfault_args[0]);
+ dbg_printf("r1 = 0x%08lx (%lu)\n", hardfault_args[1], hardfault_args[1]);
+ dbg_printf("r2 = 0x%08lx (%lu)\n", hardfault_args[2], hardfault_args[2]);
+ dbg_printf("r3 = 0x%08lx (%lu)\n", hardfault_args[3], hardfault_args[3]);
+ dbg_printf("r12 = 0x%08lx (%lu)\n", hardfault_args[4], hardfault_args[4]);
+ dbg_printf("lr = 0x%08lx (%lu)\n", hardfault_args[5], hardfault_args[5]);
+ dbg_printf("pc = 0x%08lx (%lu)\n", hardfault_args[6], hardfault_args[6]);
+ dbg_printf("psr = 0x%08lx (%lu)\n", hardfault_args[7], hardfault_args[7]);
+ dbg_printf("\n");
+
+ halt();
+}
+
+size_t strlen(const char *s) {
+ size_t size = 0;
+ while (*s++ != '\0') size++;
+ return size;
+}
+
+bool run = true;
+
+volatile USART_TypeDef *usart1 = (volatile USART_TypeDef *) USART1_BASE;
+volatile I2C_TypeDef *i2c1 = (volatile I2C_TypeDef *) I2C1_BASE;
+volatile I2C_TypeDef *i2c2 = (volatile I2C_TypeDef *) I2C2_BASE;
+
+extern "C"
+void assert_failed(uint8_t *file, uint32_t line) {
+ dbg_printf("assert_failed: %s: %" PRIu32 "\n", file, line);
+}
+
+int start_wait_count;
+
+void i2c_hard_reset(I2C_TypeDef *I2Cx, I2C_InitTypeDef &i2c_init) {
+ dbg_printf("start_wait_count=%d\n", start_wait_count);
+ I2C_DeInit(I2Cx);
+ I2C_Cmd(I2Cx, DISABLE);
+ I2C_Init(I2Cx, &i2c_init);
+
+ GPIO_InitTypeDef init;
+ GPIO_StructInit(&init);
+ init.GPIO_Pin = GPIO_Pin_10;
+ init.GPIO_Mode = GPIO_Mode_Out_PP;
+ GPIO_Init(GPIOB, &init);
+
+ GPIO_WriteBit(GPIOB, GPIO_Pin_10, Bit_RESET);
+ for (int i = 0; i < 8; i++) {
+ GPIO_WriteBit(GPIOB, GPIO_Pin_10, Bit_SET);
+ GPIO_WriteBit(GPIOB, GPIO_Pin_10, Bit_RESET);
+ }
+
+ init.GPIO_Pin = GPIO_Pin_10;
+ init.GPIO_Mode = GPIO_Mode_AF_OD;
+ GPIO_Init(GPIOB, &init);
+
+ I2C_Cmd(I2Cx, ENABLE);
+
+ I2C_SoftwareResetCmd(I2Cx, ENABLE);
+ for (int i = 0; i < 100; i++) {
+ __NOP();
+ }
+ I2C_SoftwareResetCmd(I2Cx, DISABLE);
+}
+
+static inline bool i2c_wait_for_flag(I2C_TypeDef *I2Cx, uint32_t flag, FlagStatus status, unsigned int timeout) {
+ do {
+ auto flagStatus = I2C_GetFlagStatus(I2Cx, flag);
+ if (flagStatus == status) {
+ return true;
+ }
+ } while (timeout-- > 0);
+
+ return false;
+}
+
+static inline bool i2c_wait_for_event(I2C_TypeDef *I2Cx, uint32_t expected, unsigned int timeout) {
+ uint32_t actual;
+ do {
+ actual = I2C_GetLastEvent(I2Cx);
+ if (actual == expected) {
+ return true;
+ }
+ } while (timeout-- > 0);
+
+ dbg_printf("i2c_wait_for_event, expected=%08" PRIx32 ", actual=%08" PRIx32 "\n", expected, actual);
+
+ return false;
+}
+
+const unsigned int timeout = 1000 * 1000;
+
+bool i2c_write(I2C_TypeDef *port, uint8_t address, uint8_t *buf, uint8_t count, bool generate_stop) {
+ if (!i2c_wait_for_flag(port, I2C_FLAG_BUSY, RESET, timeout)) {
+ dbg_printf("Failed while waiting for I2C_FLAG_BUSY\n");
+ return false;
+ }
+
+ I2C_GenerateSTART(port, ENABLE);
+
+ if (!i2c_wait_for_event(port, I2C_EVENT_MASTER_MODE_SELECT, timeout)) {
+ dbg_printf("Failed while waiting for I2C_EVENT_MASTER_MODE_SELECT\n");
+ return false;
+ }
+
+ I2C_Send7bitAddress(port, address, I2C_Direction_Transmitter);
+
+ if (!i2c_wait_for_event(port, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED, timeout)) {
+ dbg_printf("Failed while waiting for I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED\n");
+ return false;
+ }
+
+ do {
+ I2C_SendData(port, *buf++);
+
+ if (!i2c_wait_for_event(port, I2C_EVENT_MASTER_BYTE_TRANSMITTED, timeout)) {
+ dbg_printf("Failed while waiting for I2C_EVENT_MASTER_BYTE_TRANSMITTED\n");
+ return false;
+ }
+ } while (--count);
+
+ if (generate_stop) {
+ I2C_GenerateSTOP(port, ENABLE);
+
+ while (I2C_GetFlagStatus(port, I2C_FLAG_STOPF)) {
+ __NOP();
+ }
+ }
+
+ return true;
+}
+
+bool i2c_read(I2C_TypeDef *port, uint8_t address, uint8_t *buf, uint8_t count, bool generate_start) {
+ start_wait_count = 0;
+ int dbg_counter = 0;
+ (void) dbg_counter;
+
+ if (generate_start) {
+ if (!i2c_wait_for_flag(port, I2C_FLAG_BUSY, RESET, timeout)) {
+ dbg_printf("Failed while waiting for I2C_FLAG_BUSY\n");
+ return false;
+ }
+
+ I2C_AcknowledgeConfig(port, ENABLE);
+// dbg_printf("%2d SR2 SR1 = %08" PRIx32 "\n", dbg_counter, I2C_GetLastEvent(port));
+ I2C_NACKPositionConfig(port, I2C_NACKPosition_Current);
+// dbg_printf("%2d SR2 SR1 = %08" PRIx32 "\n", dbg_counter, I2C_GetLastEvent(port));
+
+ I2C_GenerateSTART(port, ENABLE);
+
+// dbg_printf("%2d SR2 SR1 = %08" PRIx32 "\n", dbg_counter, I2C_GetLastEvent(port));
+
+ /* I2C_EVENT_MASTER_MODE_SELECT = BUSY, MSL and SB flag */
+ if (!i2c_wait_for_event(port, I2C_EVENT_MASTER_MODE_SELECT, timeout)) {
+ dbg_printf("Failed while waiting for I2C_EVENT_MASTER_MODE_SELECT\n");
+ return false;
+ }
+
+ I2C_Send7bitAddress(port, address, I2C_Direction_Receiver);
+
+ // I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED == BUSY, MSL and ADDR
+ if (!i2c_wait_for_event(port, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED, timeout)) {
+ dbg_printf("Failed while waiting for I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED\n");
+ return false;
+ }
+ }
+
+ if (count == 1) {
+ I2C_AcknowledgeConfig(port, DISABLE);
+
+ __disable_irq();
+ (void) port->SR2;
+ I2C_GenerateSTOP(port, ENABLE);
+ __enable_irq();
+
+ while (!I2C_CheckEvent(port, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
+ __NOP();
+ }
+
+ *buf = I2C_ReceiveData(port);
+ } else if (count == 2) {
+ I2C_NACKPositionConfig(port, I2C_NACKPosition_Next);
+
+ __disable_irq();
+ (void) port->SR2;
+ I2C_AcknowledgeConfig(port, DISABLE);
+ __enable_irq();
+
+ while (!I2C_CheckEvent(port, I2C_EVENT_MASTER_BYTE_RECEIVED)) {
+ __NOP();
+ }
+
+ __disable_irq();
+ I2C_GenerateSTOP(port, ENABLE);
+ *buf++ = I2C_ReceiveData(port);
+ __enable_irq();
+ *buf = I2C_ReceiveData(port);
+ } else {
+ do {
+ if (!i2c_wait_for_event(port, I2C_EVENT_MASTER_BYTE_RECEIVED, timeout)) {
+ dbg_printf("Failed while waiting for I2C_EVENT_MASTER_BYTE_RECEIVED, count=%d\n", count);
+ return false;
+ }
+
+ *buf++ = I2C_ReceiveData(port);
+ } while (--count != 2);
+
+ I2C_AcknowledgeConfig(port, DISABLE);
+
+ __disable_irq();
+ *buf++ = I2C_ReceiveData(port);
+ I2C_GenerateSTOP(port, ENABLE);
+ __enable_irq();
+
+ *buf++ = I2C_ReceiveData(port);
+
+ if (!i2c_wait_for_event(port, I2C_EVENT_MASTER_BYTE_RECEIVED, timeout)) {
+ dbg_printf("Failed while waiting for I2C_EVENT_MASTER_BYTE_RECEIVED\n");
+ return false;
+ }
+
+ *buf = I2C_ReceiveData(port);
+ }
+
+ while (I2C_GetFlagStatus(port, I2C_FLAG_STOPF)) {
+ __NOP();
+ }
+
+ return true;
+}
+
+int main() {
+ SystemInit();
+
+ init_printf(nullptr, dbg_putc);
+
+ dbg_printf("i2c1\n");
+
+ RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO
+ | RCC_APB2Periph_USART1
+ | RCC_APB2Periph_GPIOA
+ | RCC_APB2Periph_GPIOB
+ | RCC_APB2Periph_GPIOC,
+ ENABLE);
+
+ /* ***************************************** */
+
+ // Debug on port B
+
+ RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, ENABLE);
+ RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);
+
+ // Make Port B's pin #5 the debug output pin
+ GPIO_InitTypeDef init;
+ GPIO_StructInit(&init);
+ init.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
+ init.GPIO_Mode = GPIO_Mode_Out_PP;
+ init.GPIO_Speed = GPIO_Speed_2MHz;
+ GPIO_Init(GPIOB, &init);
+
+ /* ***************************************** */
+
+ RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,
+ ENABLE);
+
+ /*
+ * PB10 I2C2_SCL
+ * PB11 I2C2_SDA
+ */
+
+ RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, ENABLE);
+ RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C2, DISABLE);
+
+ GPIO_StructInit(&init);
+ init.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
+ init.GPIO_Mode = GPIO_Mode_AF_OD;
+ GPIO_Init(GPIOB, &init);
+
+ /*
+ i2c2->CR2 |= 36; // APB1 freq is 36 MHz
+ // 36 MHz = 27.78 ns, 400 kHz = 2500ns
+ // 2500 ns / 27.78 ns = 89.99
+ i2c2->CCR |= I2C_CCR_FS | 90;
+ */
+
+ I2C_TypeDef *const i2c_port = I2C2;
+ I2C_DeInit(i2c_port);
+ I2C_InitTypeDef i2c_init;
+ I2C_StructInit(&i2c_init);
+ i2c_init.I2C_ClockSpeed = 100 * 1000;
+ i2c_init.I2C_Ack = I2C_Ack_Enable;
+ i2c_init.I2C_Mode = I2C_Mode_I2C;
+ I2C_Init(i2c_port, &i2c_init);
+ I2C_Cmd(i2c_port, ENABLE);
+
+ const int DS3231_address = 0b11010000; // 0x68
+
+ run = true;
+ bool toggle = true;
+ bool success = true;
+ while (run) {
+ GPIO_WriteBit(GPIOB, GPIO_Pin_5, toggle ? Bit_SET : Bit_RESET);
+ GPIO_WriteBit(GPIOB, GPIO_Pin_6, toggle ? Bit_SET : Bit_RESET);
+ GPIO_WriteBit(GPIOB, GPIO_Pin_7, toggle ? Bit_SET : Bit_RESET);
+ toggle = !toggle;
+
+ if (!success) {
+ dbg_printf("resetting...\n");
+ i2c_hard_reset(i2c_port, i2c_init);
+ }
+
+ uint8_t buf[12];
+ for (size_t i = 0; i < SizeOfArray(buf); i++) {
+ buf[i] = 0;
+ }
+
+ success = i2c_write(i2c_port, DS3231_address, buf, 1, false);
+
+ if (!success) {
+ dbg_printf("i2c_write failed\n");
+ continue;
+ }
+
+ success = i2c_read(i2c_port, DS3231_address, buf, SizeOfArray<uint8_t>(buf), false);
+
+ if (success) {
+ dbg_printf(
+ "%3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n"
+// "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x" /*" %02x %02x %02x %02x"*/ "\n"
+ "\n",
+// buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8],
+// buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15],
+ buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8],
+ buf[9], buf[10], buf[11]/*, buf[12], buf[13], buf[14], buf[15]*/);
+ }
+ }
+
+ return 0;
+}
+
diff --git a/cmake/stm32.toolchain.cmake b/cmake/stm32.toolchain.cmake
index 8e380fe..05a9090 100644
--- a/cmake/stm32.toolchain.cmake
+++ b/cmake/stm32.toolchain.cmake
@@ -22,12 +22,17 @@ set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_CROSSCOMPILING 1)
set(TARGET_FLAGS "-mcpu=cortex-m3 -mthumb")
-set(BASE_FLAGS "-O3 -ffreestanding -Wall -Wextra -g -ffunction-sections -fdata-sections ${TARGET_FLAGS}")
+
+set(o_level "$<TARGET_PROPERTY:O_LEVEL>")
+add_compile_options("$<$<BOOL:${o_level}>:-O${o_level}>$<$<NOT:$<BOOL:${o_level}>>:-O3>")
+unset(o_level)
+
+set(BASE_FLAGS "-ffreestanding -Wall -Wextra -g -ffunction-sections -fdata-sections ${TARGET_FLAGS}")
set(CMAKE_C_FLAGS "${BASE_FLAGS}" CACHE STRING "c flags")
set(CMAKE_CXX_FLAGS "${BASE_FLAGS} -fno-exceptions -fno-rtti -felide-constructors -std=c++14" CACHE STRING "c++ flags")
-set(LINKER_FLAGS "-O3 -nostdlib -Wl,--gc-sections ${TARGET_FLAGS}")
+set(LINKER_FLAGS "-nostdlib -Wl,--gc-sections ${TARGET_FLAGS}")
#set(LINKER_LIBS "-larm_cortexM4l_math -lm")
set(CMAKE_EXE_LINKER_FLAGS "${LINKER_FLAGS}" CACHE STRING "linker flags" FORCE)
diff --git a/gdb-apps b/gdb-apps
new file mode 100644
index 0000000..f4be9b7
--- /dev/null
+++ b/gdb-apps
@@ -0,0 +1,207 @@
+# Source this file to get all the defined commands.
+
+define flash_can1_a
+ shell cd build && make can1.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/can1/can1.elf
+ load build/apps/can1/can1.elf
+ set confirm on
+
+ hbreak halt
+end
+
+define flash_can1_b
+ shell cd build && make can1.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/can1/can1.elf
+ load build/apps/can1/can1.elf
+ set confirm on
+
+ hbreak halt
+ hbreak main
+ c
+ set variable is_client = 1
+end
+
+define flash_test1
+ shell cd build && make test1.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/test1/test1.elf
+ load build/apps/test1/test1.elf
+ set confirm on
+
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+ hbreak halt
+end
+
+define flash_serial1
+ shell cd build && make serial1.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/serial1/serial1.elf
+ load build/apps/serial1/serial1.elf
+ set confirm on
+
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+ hbreak halt
+end
+
+define flash_serial2
+ shell cd build && make serial2.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/serial2/serial2.elf
+ load build/apps/serial2/serial2.elf
+ set confirm on
+
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+ hbreak halt
+end
+
+define flash_stepper1
+ shell cd build && make stepper1.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/stepper1/stepper1.elf
+ load build/apps/stepper1/stepper1.elf
+ set confirm on
+
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+ hbreak halt
+end
+
+define flash_stepper2
+ shell cd build && make stepper2.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/stepper2/stepper2.elf
+ load build/apps/stepper2/stepper2.elf
+ set confirm on
+
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+ hbreak halt
+end
+
+define flash_i2c1
+ shell cd build && make i2c1.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/i2c1/i2c1.elf
+ load build/apps/i2c1/i2c1.elf
+ set confirm on
+
+ set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+
+ echo Run this if first run:\n hbreak halt\n hbreak job1\n hbreak PendSV_Handler\n
+end
+
+define flash_os1
+ shell cd build && make os1.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/os1/os1.elf
+ load build/apps/os1/os1.elf
+ set confirm on
+
+ set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+
+ echo Run this if first run:\n hbreak halt\n hbreak job1\n hbreak PendSV_Handler\n
+end
+
+define flash_os2
+ shell cd build && make os2.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/os2/os2.elf
+ load build/apps/os2/os2.elf
+ set confirm on
+
+ set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+
+ echo Run this if first run:\n hbreak halt\n hbreak job1\n hbreak PendSV_Handler\n
+end
+
+define flash_dma1
+ shell cd build && make dma1.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/dma1/dma1.elf
+ load build/apps/dma1/dma1.elf
+ set confirm on
+
+ set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+
+ echo Run this if first run:\n hbreak halt\n
+end
+
+define flash_cpp1
+ shell cd build && make cpp1.elf
+
+ monitor arm semihosting enable
+ monitor reset halt
+
+ set confirm off
+ file build/apps/cpp1/cpp1.elf
+ load build/apps/cpp1/cpp1.elf
+ set confirm on
+
+ set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
+ monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
+
+ echo Run this if first run:\n hbreak halt\n
+end
+
+define flash_sim1
+ shell cd build && make sim1.elf
+
+ set confirm off
+ target remote tcp:localhost:3333
+ file build/apps/sim1/sim1.elf
+ load build/apps/sim1/sim1.elf
+ set confirm on
+
+ set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
+
+ hbreak halt
+end
+
diff --git a/gdb-start b/gdb-start
index fbd8789..906724d 100644
--- a/gdb-start
+++ b/gdb-start
@@ -1,146 +1,3 @@
target remote tcp:localhost:3333
monitor reset halt
set remotetimeout 10
-
-define flash_test1
- shell cd build && make test1.elf
-
- monitor arm semihosting enable
- monitor reset halt
-
- set confirm off
- file build/apps/test1/test1.elf
- load build/apps/test1/test1.elf
- set confirm on
-
- monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
- hbreak halt
-end
-
-define flash_serial1
- shell cd build && make serial1.elf
-
- monitor arm semihosting enable
- monitor reset halt
-
- set confirm off
- file build/apps/serial1/serial1.elf
- load build/apps/serial1/serial1.elf
- set confirm on
-
- monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
- hbreak halt
-end
-
-define flash_serial2
- shell cd build && make serial2.elf
-
- monitor arm semihosting enable
- monitor reset halt
-
- set confirm off
- file build/apps/serial2/serial2.elf
- load build/apps/serial2/serial2.elf
- set confirm on
-
- monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
- hbreak halt
-end
-
-define flash_stepper1
- shell cd build && make stepper1.elf
-
- monitor arm semihosting enable
- monitor reset halt
-
- set confirm off
- file build/apps/stepper1/stepper1.elf
- load build/apps/stepper1/stepper1.elf
- set confirm on
-
- monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
- hbreak halt
-end
-
-define flash_stepper2
- shell cd build && make stepper2.elf
-
- monitor arm semihosting enable
- monitor reset halt
-
- set confirm off
- file build/apps/stepper2/stepper2.elf
- load build/apps/stepper2/stepper2.elf
- set confirm on
-
- monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
- hbreak halt
-end
-
-define flash_os1
- shell cd build && make os1.elf
-
- monitor arm semihosting enable
- monitor reset halt
-
- set confirm off
- file build/apps/os1/os1.elf
- load build/apps/os1/os1.elf
- set confirm on
-
- set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
- monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
-
- echo Run this if first run:\n hbreak halt\n hbreak job1\n hbreak PendSV_Handler\n
-end
-
-define flash_os2
- shell cd build && make os2.elf
-
- monitor arm semihosting enable
- monitor reset halt
-
- set confirm off
- file build/apps/os2/os2.elf
- load build/apps/os2/os2.elf
- set confirm on
-
- set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
- monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
-
- echo Run this if first run:\n hbreak halt\n hbreak job1\n hbreak PendSV_Handler\n
-end
-
-define flash_dma1
- shell cd build && make dma1.elf
-
- monitor arm semihosting enable
- monitor reset halt
-
- set confirm off
- file build/apps/dma1/dma1.elf
- load build/apps/dma1/dma1.elf
- set confirm on
-
- set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
- monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
-
- echo Run this if first run:\n hbreak halt\n
-end
-
-define flash_cpp1
- shell cd build && make cpp1.elf
-
- monitor arm semihosting enable
- monitor reset halt
-
- set confirm off
- file build/apps/cpp1/cpp1.elf
- load build/apps/cpp1/cpp1.elf
- set confirm on
-
- set $r0=0, $r1=-1, $r2=-2, $r3=-3, $r4=-4, $r5=-5, $r6=-6, $r7=-7, $r8=-8, $r9=-9, $r10=-10, $r11=-11, $r12=-12
- monitor stm32f1x.cpu mwb 0x20000000 0x5a 20480
-
- echo Run this if first run:\n hbreak halt\n
-end
diff --git a/html/module.png b/html/module.png
new file mode 100644
index 0000000..d97cc47
--- /dev/null
+++ b/html/module.png
Binary files differ
diff --git a/html/pinout-2.html b/html/pinout-2.html
new file mode 100644
index 0000000..40a98f4
--- /dev/null
+++ b/html/pinout-2.html
@@ -0,0 +1,519 @@
+<html>
+<head>
+ <style type="text/css">
+ table.pinout {
+ border-spacing: 0;
+ /*border-style: solid;*/
+
+ font-family: "Arial", "sans-serif";
+ font-weight: bold;
+ }
+
+ table.pinout td.group-tim2 {
+ background-color: indianred;
+ border-style: none;
+ }
+
+ table.pinout td.group-adc12 {
+ background-color: deepskyblue;
+ border-style: none;
+ }
+
+ table.pinout td.group-usart2 {
+ background-color: lawngreen;
+ border-style: none;
+ }
+
+ table.pinout td.group-spi1 {
+ background-color: sandybrown;
+ border-style: none;
+ }
+
+ table.pinout td {
+ white-space: nowrap;
+ }
+
+ td.connection {
+ }
+
+ table.pinout td {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ }
+
+ .group-top {
+ border: 1px solid;
+ border-bottom-width: 0;
+ border-top-left-radius: 0.5rem;
+ border-top-right-radius: 0.5rem;
+ }
+
+ .group-bottom {
+ border: 1px solid;
+ border-top-width: 0;
+ border-bottom-left-radius: 0.5rem;
+ border-bottom-right-radius: 0.5rem;
+ }
+
+ .group-middle {
+ border-left: 1px solid;
+ border-right: 1px solid;
+ }
+
+ .group-one {
+ border: 1px;
+ border-radius: 0.5rem;
+
+ background-color: black;
+ color: white;
+ text-align: center;
+ }
+
+ .group-single {
+ border: 1px;
+ border-radius: 0.5rem;
+
+ text-align: center;
+ }
+
+ .connection {
+ width: 3rem;
+ }
+
+ </style>
+ <style type="text/css">
+ table.container {
+ border-collapse: collapse;
+ }
+
+ table.container td.top-spacer {
+ width: 190px;
+ /*border: 2px green;*/
+ }
+
+ table.container td.bottom-spacer {
+ width: 165px;
+ /*border: 2px green;*/
+
+ /*
+ text-align: center;
+ content: "spacer";
+ */
+ }
+ </style>
+ <script type="application/javascript">
+ // group
+ function g(group, name, remapped) {
+ return {
+ group: group,
+ name: name,
+ remapped: !!remapped
+ };
+ }
+
+ // one
+ function o(name) {
+ return {
+ name: name
+ };
+ }
+
+ // empty
+ function e() {
+ return {};
+ }
+
+ function pin() {
+ var functions = [];
+ functions.push({name: arguments[0]});
+ for (var i = 1; i < arguments.length; i++) {
+ functions.push(arguments[i]);
+ }
+ return new Pin(arguments[0], functions);
+ }
+
+ /**
+ * @constructor
+ */
+ function Pin(name, functions) {
+ function hasGroup(group) {
+ return functions.some(function (f) {
+ return f.group == group;
+ });
+ }
+
+ /**
+ * @lends Pin.prototype
+ */
+ return {
+ name: name,
+ functions: functions,
+ hasGroup: hasGroup
+ };
+ }
+
+ /**
+ * @constructor
+ */
+ function Header(columns, pins) {
+ var rows = pins.length / columns;
+
+ function pinsOnColumn(column) {
+ var ps = [];
+
+ for (var i = column; i < pins.length; i += columns) {
+ ps.push(pins[i]);
+ }
+
+ return ps;
+ }
+
+ /**
+ * @return {Pin}
+ */
+ function at(column, row) {
+ return pins[row * columns + column];
+ }
+
+ /**
+ * @return {Pin}
+ */
+ function above(column, row) {
+ return at(column, row - 1);
+ }
+
+ /**
+ * @return {Pin}
+ */
+ function below(column, row) {
+ return at(column, row + 1);
+ }
+
+ function maxNumberOfFunctionsInColumn(column) {
+ var width = 0;
+ for (var i = column; i < pins.length; i += columns) {
+ width = Math.max(width, pins[i].functions.length);
+ }
+
+ return width;
+ }
+
+ /**
+ * @lends Header.prototype
+ */
+ return {
+ at: at,
+ above: above,
+ below: below,
+ pinsOnColumn: pinsOnColumn,
+ maxNumberOfFunctionsInColumn: maxNumberOfFunctionsInColumn,
+ rowCount: rows
+ }
+ }
+
+ var j8 = new Header(2, [
+ pin("3V3"),
+ pin("3V3"),
+ pin("PA0", o("WKUP"), g("usart2", "USART2_CTS"), g("adc12", "ADC12_IN0"), g("tim2", "TIM2_CH1_ETR")),
+ pin("PA1", e(), g("usart2", "USART2_RTS"), g("adc12", "ADC12_IN1"), g("tim2", "TIM2_CH2")),
+ pin("PA2", e(), g("usart2", "USART2_TX"), g("adc12", "ADC12_IN2"), g("tim2", "TIM2_CH3")),
+ pin("PA3", e(), g("usart2", "USART2_RX"), g("adc12", "ADC12_IN3"), g("tim2", " TIM2_CH4")),
+ pin("PA4", g("spi1", "SPI1_NSS"), g("usart2", "USART2_CK"), g("adc12", "ADC12_IN4")),
+ pin("PA5", g("spi1", "SPI1_SCK"), e(), g("adc12", "ADC12_IN5")),
+ pin("PA6", g("spi1", "SPI1_MISO"), g("tim1", "TIM1_BKIN", true), g("adc12", "ADC12_IN6"), g("tim3", "TIM3_CH1")),
+ pin("PA7", g("spi1", "SPI1_MOSI"), g("tim1", "TIM1_CH1N", true), g("adc12", "ADC12_IN7"), g("tim3", "TIM3_CH2")),
+ pin("PB0", e(), g("tim1", "TIM1_CH2N", true), g("adc12", "ADC12_IN8"), g("tim3", "TIM3_CH3")),
+ pin("PB1", e(), g("tim1", "TIM1_CH3N", true), g("adc12", "ADC12_IN8"), g("tim3", "TIM3_CH3")),
+ pin("PB2", o("boot1")),
+ pin("PB10", e(), g("usart3", "USART3_TX"), g("i2c2", "I2C2_SCL"), g("tim2", "TIM2_CH3", true)),
+ pin("PB12", g("spi2", "SPI2_NSS"), g("usart3", "USART3_CK"), g("i2c2", "I2C2_SMBAl"), g("tim1", "TIM1_BKIN")),
+ pin("PB11", e(), g("usart3", "USART3_RX"), g("i2c2", "I2C2_SDA"), g("tim2", "TIM2_CH4", true)),
+ pin("PB14", g("spi2", "SPI2_MISO"), g("usart3", "USART3_RTS"), e(), g("tim1", "TIM1_CH2N")),
+ pin("PB13", g("spi2", "SPI2_SCK"), g("usart3", "USART3_CTS"), g("tim1", "TIM1_CH1N")),
+ pin("PB8", o("MCO"), g("usart1", "USART1_CK"), e(), g("tim1", "TIM1_CH1")),
+ pin("PB15", g("spi2", "SPI2_MOSI"), e(), g("tim1", "TIM1_CH3N")),
+ pin("PB10", e(), g("usart1", "USART1_RX"), e(), g("tim1", "TIM1_CH3")),
+ pin("PB9"),
+ pin("GND"),
+ pin("GND")
+ ]);
+
+ var j9 = new Header(2, [
+ pin("3V3"),
+ pin("3V3"),
+ pin("NRST"),
+ pin("PD1", g("can", "CANTX")),
+ pin("PD0", g("can", "CANRX")),
+ pin("PC15", o("OSC32_OUT")),
+ pin("PC14", o("OSC32_IN")),
+ pin("PC13", o("TAMPER-RTC")),
+ pin("Vbat"),
+ pin("PB9", g("tim4", "TIM4_CH4"), g("i2c1", "I2C1_SDA", true), g("can", "CANTX", true)),
+ pin("PB8", g("tim4", "TIM4_CH3"), g("i2c1", "I2C1_SCL", true), g("can", "CANRX", true)),
+ pin("BOOT0"),
+ pin("PB7", g("tim4", "TIM4_CH2"), g("i2c1", "I2C1_SDA"), g("usart1", "USART1_RX", true)),
+ pin("PB6", g("tim4", "TIM4_CH1"), g("i2c1", "I2C1_SCL"), g("usart1", "USART1_TX", true)),
+ pin("PB5", g("tim3", "TIM3_CH2", true), g("i2c1", "I2C1_SMBAl"), g("spi1", "SPI1_MOSI", true)),
+ pin("PB4", g("jtag", "JNTRST" /* default */), g("tim3", "TIM3_CH1", true), g("gpio", "PB4", true), g("spi1", "SPI1_MISO", true)),
+ pin("PB3", g("jtag", "JTDO" /* default */), g("tim2", "TIM2_CH2", true), g("gpio", "PB3", true), g("spi1", "SPI1_SCK", true), g("jtag", "TRACESWO", true)),
+ pin("PA15", g("jtag", "JTDI" /* default */), g("tim2", "TIM2_CH1_ETR", true), g("gpio", "PA15", true), g("spi1", "SPI1_NSS", true)),
+ pin("PA14", g("jtag", "JTCK/SWCLK" /* default */), e(), g("gpio", "PA14", true)),
+ pin("PA13", g("jtag", "JTMS/SWDIO" /* default */), e(), g("gpio", "PA13", true)),
+ pin("PA12", g("usb", "USBDP"), g("usart1", "USART1_RTS"), g("can", "CANTX"), g("tim1", "TIM1_ETR")),
+ pin("PA11", g("usb", "USBDM"), g("usart1", "USART1_CTS"), g("can", "CANRX"), g("tim1", "TIM1_CH4")),
+ pin("GND"),
+ pin("GND")
+ ]);
+
+ var headers = {
+ j8: j8,
+ j9: j9
+ };
+
+ /**
+ * @param {Element} table
+ */
+ function generate(table, headerName, side) {
+ /**
+ * @type {Header}
+ */
+ var header = headers[headerName];
+ if (!header) {
+ return;
+ }
+
+ var d = table.ownerDocument;
+ var left = side == "left";
+ var column = left ? 0 : 1;
+
+ var width = header.maxNumberOfFunctionsInColumn(column);
+ console.log('width', width);
+
+ (function() {
+ for (var row = header.rowCount; row >= 0; row--) {
+ var pin = header.at(column, row);
+
+ var tr = d.createElement("tr");
+ table.appendChild(tr);
+ }
+ })();
+
+ if(false)
+ for (var row = 0; row < header.rowCount; row++) {
+ var pin = header.at(column, row);
+ console.log("pin: ", pin);
+
+ var tr = d.createElement("tr");
+ table.appendChild(tr);
+
+ var spacers = [], td;
+ for (var j = 0; j < (width - pin.functions.length); j++) {
+ td = document.createElement("td");
+ spacers.push(td);
+ td = document.createElement("td");
+ td.setAttribute("class", "connection");
+ spacers.push(td);
+ }
+
+ if (left) {
+ spacers.forEach(function (e) {
+ tr.appendChild(e);
+ });
+ }
+
+ for (var fi = left ? pin.functions.length - 1 : 0; fi >= 0 && fi < pin.functions.length; fi += left ? -1 : 1) {
+ var f = pin.functions[fi];
+// console.log("f:", fi, f);
+ var text = '';
+ if (f.name) {
+ text = f.name;
+ if (f.remapped) {
+ text += " (r)";
+ }
+ }
+
+ td = d.createElement("td");
+ var cls = '';
+ if (f.group) {
+ cls += " group-" + f.group;
+
+ var above = header.above(column, row);
+ var below = header.below(column, row);
+ console.log('f', f, 'above', above, 'below', below);
+ above = above && above.hasGroup(f.group);
+ below = below && below.hasGroup(f.group);
+
+ if (!above && !below) {
+ cls += " group-single";
+ } else if (!above && below) {
+ cls += " group-top";
+ } else if (above && below) {
+ cls += " group-middle";
+ } else if (above && !below) {
+ cls += " group-bottom";
+ }
+ } else {
+ cls = " group-one";
+ }
+
+ if (f.remapped) {
+ cls += " group-remapped";
+ }
+
+ if (text.trim() != "") {
+ td.setAttribute("class", cls);
+ }
+
+ td.appendChild(document.createTextNode(text));
+ tr.appendChild(td);
+ td = document.createElement("td");
+ td.setAttribute("class", "connection");
+ tr.appendChild(td);
+ }
+
+ if (!left) {
+ spacers.forEach(function (e) {
+ tr.appendChild(e);
+ });
+ }
+
+ // <tr>
+ // <td class="group-top group-tim2">
+ // TIM2_CH1_ETR
+ // </td>
+ // <td class="connection"></td>
+ // <td class="group-top group-adc12">
+ // ADC12_IN0
+ // </td>
+ // <td class="connection"></td>
+ // <td class="group-top group-usart2">
+ // USART2_CTS
+ // </td>
+ // <td class="connection"></td>
+ // <td class="group-one">
+ // WKUP
+ // </td>
+ // <td class="connection"></td>
+ // <td class="group-one">
+ // PA0
+ // </td>
+ // </tr>
+ }
+ }
+
+ function doOnLoad() {
+ console.log('j8', j8);
+ var items = document.getElementsByClassName("pinout");
+ for (var i = 0; i < items.length; i++) {
+ var e = items[i];
+ var classes = e.attributes.class.value.split(" ");
+ var generatePinout = false, header, side;
+ for (var j = 0; j < classes.length; j++) {
+ var c = classes[j];
+
+ if (c.match(/pinout/)) {
+ generatePinout = true;
+ } else if (c.match(/^header-([0-9]*)/)) {
+ header = c.replace(/^header-([0-9]*)/, "$1");
+ } else if (c.match(/^side-/)) {
+ side = c.replace(/^side-(.*)/, "$1");
+ }
+ }
+
+ if (generatePinout) {
+ console.log('generating', header, side);
+ generate(e, header, side);
+ }
+ }
+ }
+ window.onload = doOnLoad;
+ </script>
+</head>
+<body>
+<table border="1" class="container">
+ <tr>
+ <td class="bottom-spacer" rowspan="2">
+ </td>
+ <td>
+ <table class="pinout header-j8 side-left"></table>
+ </td>
+ <!--
+ <td>
+ <table>
+ <tr>
+ <td>
+
+ </td>
+ <td>
+ USART1_RX
+ </td>
+ <td>
+
+ </td>
+ </tr>
+ <tr>
+ <td>
+
+ </td>
+ <td>
+
+ </td>
+ <td>
+ MCO
+ </td>
+ </tr>
+ <tr>
+ <td>
+ GND
+ </td>
+ <td>
+ PB10
+ </td>
+ <td>
+ PB8
+ </td>
+ </tr>
+ </table>
+ </td>
+ -->
+ <td class="top-spacer" rowspan="2">
+ top space
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table class="pinout header-j8 side-right"></table>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <img src="module-horizontal.png"/>
+ </td>
+ </tr>
+ <tr>
+ <!--
+ <td>
+ <table class="pinout header-j8 side-left"></table>
+ </td>
+ <td>
+ <table class="pinout header-j8 side-right"></table>
+ </td>
+ <td>
+ <table class="pinout header-j9 side-left"></table>
+ </td>
+ <td>
+ <table class="pinout header-j9 side-right"></table>
+ </td>
+ -->
+ </tr>
+ <!--
+ <tr>
+ <td colspan="2" class="bottom-spacer"></td>
+ </tr>
+ -->
+ <tr>
+ </tr>
+</table>
+
+</body>
+</html>
diff --git a/html/pinout.html b/html/pinout.html
new file mode 100644
index 0000000..a9f17e0
--- /dev/null
+++ b/html/pinout.html
@@ -0,0 +1,682 @@
+<html>
+<head>
+ <style type="text/css">
+ table.pinout {
+ border-spacing: 0;
+ /*border-style: solid;*/
+
+ font-family: "Arial", "sans-serif";
+ font-weight: bold;
+ }
+
+ table.pinout td.group-tim2 {
+ background-color: indianred;
+ border-style: none;
+ }
+
+ table.pinout td.group-adc12 {
+ background-color: deepskyblue;
+ border-style: none;
+ }
+
+ table.pinout td.group-usart2 {
+ background-color: lawngreen;
+ border-style: none;
+ }
+
+ table.pinout td.group-spi1 {
+ background-color: sandybrown;
+ border-style: none;
+ }
+
+ table.pinout td {
+ white-space: nowrap;
+ }
+
+ td.connection {
+ }
+
+ table.pinout td {
+ padding-left: 0.5rem;
+ padding-right: 0.5rem;
+ }
+
+ .group-top {
+ border: 1px solid;
+ border-bottom-width: 0;
+ border-top-left-radius: 0.5rem;
+ border-top-right-radius: 0.5rem;
+ }
+
+ .group-bottom {
+ border: 1px solid;
+ border-top-width: 0;
+ border-bottom-left-radius: 0.5rem;
+ border-bottom-right-radius: 0.5rem;
+ }
+
+ .group-middle {
+ border-left: 1px solid;
+ border-right: 1px solid;
+ }
+
+ .group-one {
+ border: 1px;
+ border-radius: 0.5rem;
+
+ background-color: black;
+ color: white;
+ text-align: center;
+ }
+
+ .group-single {
+ border: 1px;
+ border-radius: 0.5rem;
+
+ text-align: center;
+ }
+
+ .connection {
+ width: 3rem;
+ }
+
+ </style>
+ <style type="text/css">
+ table.container {
+ border-collapse: collapse;
+ }
+
+ table.container td.top-spacer {
+ height: 190px;
+ /*border: 2px green;*/
+ }
+
+ table.container td.bottom-spacer {
+ height: 165px;
+ /*border: 2px green;*/
+
+ /*
+ text-align: center;
+ content: "spacer";
+ */
+ }
+ </style>
+ <script type="application/javascript">
+ // group
+ function g(group, name, remapped) {
+ return {
+ group: group,
+ name: name,
+ remapped: !!remapped
+ };
+ }
+
+ // one
+ function o(name) {
+ return {
+ name: name
+ };
+ }
+
+ // empty
+ function e() {
+ return {};
+ }
+
+ function pin() {
+ var functions = [];
+ functions.push({name: arguments[0]});
+ for (var i = 1; i < arguments.length; i++) {
+ functions.push(arguments[i]);
+ }
+ return new Pin(arguments[0], functions);
+ }
+
+ /**
+ * @constructor
+ */
+ function Pin(name, functions) {
+ function hasGroup(group) {
+ return functions.some(function (f) {
+ return f.group == group;
+ });
+ }
+
+ /**
+ * @lends Pin.prototype
+ */
+ return {
+ name: name,
+ functions: functions,
+ hasGroup: hasGroup
+ };
+ }
+
+ /**
+ * @constructor
+ */
+ function Header(columns, pins) {
+ var rows = pins.length / columns;
+
+ function pinsOnColumn(column) {
+ var ps = [];
+
+ for (var i = column; i < pins.length; i += columns) {
+ ps.push(pins[i]);
+ }
+
+ return ps;
+ }
+
+ /**
+ * @return {Pin}
+ */
+ function at(column, row) {
+ return pins[row * columns + column];
+ }
+
+ /**
+ * @return {Pin}
+ */
+ function above(column, row) {
+ return at(column, row - 1);
+ }
+
+ /**
+ * @return {Pin}
+ */
+ function below(column, row) {
+ return at(column, row + 1);
+ }
+
+ function maxNumberOfFunctionsInColumn(column) {
+ var width = 0;
+ for (var i = column; i < pins.length; i += columns) {
+ width = Math.max(width, pins[i].functions.length);
+ }
+
+ return width;
+ }
+
+ /**
+ * @lends Header.prototype
+ */
+ return {
+ at: at,
+ above: above,
+ below: below,
+ pinsOnColumn: pinsOnColumn,
+ maxNumberOfFunctionsInColumn: maxNumberOfFunctionsInColumn,
+ rowCount: rows
+ }
+ }
+
+ var j8 = new Header(2, [
+ pin("3V3"),
+ pin("3V3"),
+ pin("PA0", o("WKUP"), g("usart2", "USART2_CTS"), g("adc12", "ADC12_IN0"), g("tim2", "TIM2_CH1_ETR")),
+ pin("PA1", e(), g("usart2", "USART2_RTS"), g("adc12", "ADC12_IN1"), g("tim2", "TIM2_CH2")),
+ pin("PA2", e(), g("usart2", "USART2_TX"), g("adc12", "ADC12_IN2"), g("tim2", "TIM2_CH3")),
+ pin("PA3", e(), g("usart2", "USART2_RX"), g("adc12", "ADC12_IN3"), g("tim2", " TIM2_CH4")),
+ pin("PA4", g("spi1", "SPI1_NSS"), g("usart2", "USART2_CK"), g("adc12", "ADC12_IN4")),
+ pin("PA5", g("spi1", "SPI1_SCK"), e(), g("adc12", "ADC12_IN5")),
+ pin("PA6", g("spi1", "SPI1_MISO"), g("tim1", "TIM1_BKIN", true), g("adc12", "ADC12_IN6"), g("tim3", "TIM3_CH1")),
+ pin("PA7", g("spi1", "SPI1_MOSI"), g("tim1", "TIM1_CH1N", true), g("adc12", "ADC12_IN7"), g("tim3", "TIM3_CH2")),
+ pin("PB0", e(), g("tim1", "TIM1_CH2N", true), g("adc12", "ADC12_IN8"), g("tim3", "TIM3_CH3")),
+ pin("PB1", e(), g("tim1", "TIM1_CH3N", true), g("adc12", "ADC12_IN8"), g("tim3", "TIM3_CH3")),
+ pin("PB2", o("boot1")),
+ pin("PB10", e(), g("usart3", "USART3_TX"), g("i2c2", "I2C2_SCL"), g("tim2", "TIM2_CH3", true)),
+ pin("PB12", g("spi2", "SPI2_NSS"), g("usart3", "USART3_CK"), g("i2c2", "I2C2_SMBAl"), g("tim1", "TIM1_BKIN")),
+ pin("PB11", e(), g("usart3", "USART3_RX"), g("i2c2", "I2C2_SDA"), g("tim2", "TIM2_CH4", true)),
+ pin("PB14", g("spi2", "SPI2_MISO"), g("usart3", "USART3_RTS"), e(), g("tim1", "TIM1_CH2N")),
+ pin("PB13", g("spi2", "SPI2_SCK"), g("usart3", "USART3_CTS"), g("tim1", "TIM1_CH1N")),
+ pin("PB8", o("MCO"), g("usart1", "USART1_CK"), e(), g("tim1", "TIM1_CH1")),
+ pin("PB15", g("spi2", "SPI2_MOSI"), e(), g("tim1", "TIM1_CH3N")),
+ pin("PB10", e(), g("usart1", "USART1_RX"), e(), g("tim1", "TIM1_CH3")),
+ pin("PB9"),
+ pin("GND"),
+ pin("GND")
+ ]);
+
+ var j9 = new Header(2, [
+ pin("3V3"),
+ pin("3V3"),
+ pin("NRST"),
+ pin("PD1", g("can", "CANTX")),
+ pin("PD0", g("can", "CANRX")),
+ pin("PC15", o("OSC32_OUT")),
+ pin("PC14", o("OSC32_IN")),
+ pin("PC13", o("TAMPER-RTC")),
+ pin("Vbat"),
+ pin("PB9", g("tim4", "TIM4_CH4"), g("i2c1", "I2C1_SDA", true), g("can", "CANTX", true)),
+ pin("PB8", g("tim4", "TIM4_CH3"), g("i2c1", "I2C1_SCL", true), g("can", "CANRX", true)),
+ pin("BOOT0"),
+ pin("PB7", g("tim4", "TIM4_CH2"), g("i2c1", "I2C1_SDA"), g("usart1", "USART1_RX", true)),
+ pin("PB6", g("tim4", "TIM4_CH1"), g("i2c1", "I2C1_SCL"), g("usart1", "USART1_TX", true)),
+ pin("PB5", g("tim3", "TIM3_CH2", true), g("i2c1", "I2C1_SMBAl"), g("spi1", "SPI1_MOSI", true)),
+ pin("PB4", g("jtag", "JNTRST" /* default */), g("tim3", "TIM3_CH1", true), g("gpio", "PB4", true), g("spi1", "SPI1_MISO", true)),
+ pin("PB3", g("jtag", "JTDO" /* default */), g("tim2", "TIM2_CH2", true), g("gpio", "PB3", true), g("spi1", "SPI1_SCK", true), g("jtag", "TRACESWO", true)),
+ pin("PA15", g("jtag", "JTDI" /* default */), g("tim2", "TIM2_CH1_ETR", true), g("gpio", "PA15", true), g("spi1", "SPI1_NSS", true)),
+ pin("PA14", g("jtag", "JTCK/SWCLK" /* default */), e(), g("gpio", "PA14", true)),
+ pin("PA13", g("jtag", "JTMS/SWDIO" /* default */), e(), g("gpio", "PA13", true)),
+ pin("PA12", g("usb", "USBDP"), g("usart1", "USART1_RTS"), g("can", "CANTX"), g("tim1", "TIM1_ETR")),
+ pin("PA11", g("usb", "USBDM"), g("usart1", "USART1_CTS"), g("can", "CANRX"), g("tim1", "TIM1_CH4")),
+ pin("GND"),
+ pin("GND")
+ ]);
+
+ var headers = {
+ j8: j8,
+ j9: j9
+ };
+
+ /**
+ * @param {Element} table
+ */
+ function generate(table, headerName, side) {
+ /**
+ * @type {Header}
+ */
+ var header = headers[headerName];
+ if (!header) {
+ return;
+ }
+
+ var d = table.ownerDocument;
+ var left = side == "left";
+ var column = left ? 0 : 1;
+
+ var width = header.maxNumberOfFunctionsInColumn(column);
+ console.log('width', width);
+
+ for (var row = 0; row < header.rowCount; row++) {
+ var pin = header.at(column, row);
+ console.log("pin: ", pin);
+
+ var tr = d.createElement("tr");
+ table.appendChild(tr);
+
+ var spacers = [], td;
+ for (var j = 0; j < (width - pin.functions.length); j++) {
+ td = document.createElement("td");
+ spacers.push(td);
+ td = document.createElement("td");
+ td.setAttribute("class", "connection");
+ spacers.push(td);
+ }
+
+ if (left) {
+ spacers.forEach(function (e) {
+ tr.appendChild(e);
+ });
+ }
+
+ for (var fi = left ? pin.functions.length - 1 : 0; fi >= 0 && fi < pin.functions.length; fi += left ? -1 : 1) {
+ var f = pin.functions[fi];
+// console.log("f:", fi, f);
+ var text = '';
+ if (f.name) {
+ text = f.name;
+ if (f.remapped) {
+ text += " (r)";
+ }
+ }
+
+ td = d.createElement("td");
+ var cls = '';
+ if (f.group) {
+ cls += " group-" + f.group;
+
+ var above = header.above(column, row);
+ var below = header.below(column, row);
+ console.log('f', f, 'above', above, 'below', below);
+ above = above && above.hasGroup(f.group);
+ below = below && below.hasGroup(f.group);
+
+ if (!above && !below) {
+ cls += " group-single";
+ } else if (!above && below) {
+ cls += " group-top";
+ } else if (above && below) {
+ cls += " group-middle";
+ } else if (above && !below) {
+ cls += " group-bottom";
+ }
+ } else {
+ cls = " group-one";
+ }
+
+ if (f.remapped) {
+ cls += " group-remapped";
+ }
+
+ if (text.trim() != "") {
+ td.setAttribute("class", cls);
+ }
+
+ td.appendChild(document.createTextNode(text));
+ tr.appendChild(td);
+ td = document.createElement("td");
+ td.setAttribute("class", "connection");
+ tr.appendChild(td);
+ }
+
+ if (!left) {
+ spacers.forEach(function (e) {
+ tr.appendChild(e);
+ });
+ }
+
+ // <tr>
+ // <td class="group-top group-tim2">
+ // TIM2_CH1_ETR
+ // </td>
+ // <td class="connection"></td>
+ // <td class="group-top group-adc12">
+ // ADC12_IN0
+ // </td>
+ // <td class="connection"></td>
+ // <td class="group-top group-usart2">
+ // USART2_CTS
+ // </td>
+ // <td class="connection"></td>
+ // <td class="group-one">
+ // WKUP
+ // </td>
+ // <td class="connection"></td>
+ // <td class="group-one">
+ // PA0
+ // </td>
+ // </tr>
+ }
+ }
+
+ function doOnLoad() {
+ console.log('j8', j8);
+ var items = document.getElementsByClassName("pinout");
+ for (var i = 0; i < items.length; i++) {
+ var e = items[i];
+ var classes = e.attributes.class.value.split(" ");
+ var generatePinout = false, header, side;
+ for (var j = 0; j < classes.length; j++) {
+ var c = classes[j];
+
+ if (c.match(/pinout/)) {
+ generatePinout = true;
+ } else if (c.match(/^header-([0-9]*)/)) {
+ header = c.replace(/^header-([0-9]*)/, "$1");
+ } else if (c.match(/^side-/)) {
+ side = c.replace(/^side-(.*)/, "$1");
+ }
+ }
+
+ if (generatePinout) {
+ console.log('generating', header, side);
+ generate(e, header, side);
+ }
+ }
+ }
+ window.onload = doOnLoad;
+ </script>
+</head>
+<body>
+<table border="1" class="container">
+ <tr>
+ <td colspan="2" class="top-spacer">
+ </td>
+ <td rowspan="3">
+ <img src="module.png">
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <table class="pinout header-j8 side-left"></table>
+ </td>
+ <td>
+ <table class="pinout header-j8 side-right"></table>
+ </td>
+ <td>
+ <table class="pinout header-j9 side-left"></table>
+ </td>
+ <td>
+ <table class="pinout header-j9 side-right"></table>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="2" class="bottom-spacer"></td>
+ </tr>
+ <tr>
+ </tr>
+</table>
+
+<!--
+<table class="pinout">
+ <tr>
+ <td colspan="8" class="connection"></td>
+ <td class="group-one">
+ 3.3V
+ </td>
+ </tr>
+
+ <tr>
+ <td class="group-top group-tim2">
+ TIM2_CH1_ETR
+ </td>
+ <td class="connection"></td>
+ <td class="group-top group-adc12">
+ ADC12_IN0
+ </td>
+ <td class="connection"></td>
+ <td class="group-top group-usart2">
+ USART2_CTS
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ WKUP
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ PA0
+ </td>
+ </tr>
+
+ <tr>
+ <td class="group-bottom group-tim2">
+ TIM2_CH3
+ </td>
+ <td class="connection"></td>
+ <td class="group-middle group-adc12">
+ ADC12_IN2
+ </td>
+ <td class="connection"></td>
+ <td class="group-middle group-usart2">
+ USART2_TX
+ </td>
+ <td class="connection"></td>
+ <td>
+ &nbsp;
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ PA2
+ </td>
+ </tr>
+
+ <tr>
+ <td class="">
+ </td>
+ <td class="connection"></td>
+ <td class="group-middle group-adc12">
+ ADC12_IN4
+ </td>
+ <td class="connection"></td>
+ <td class="group-bottom group-usart2">
+ USART2_CK
+ </td>
+ <td class="connection"></td>
+ <td class="group-top group-spi1">
+ SPI1_NSS
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ PA4
+ </td>
+ </tr>
+
+ <tr>
+ <td class="group-top">
+ TIM3_CH1
+ </td>
+ <td class="connection"></td>
+ <td class="group-middle group-adc12">
+ ADC12_IN6
+ </td>
+ <td class="connection" colspan="3"></td>
+ <td class="group-bottom group-spi1">
+ SPI1_MISO
+ <td class="connection"></td>
+ <td class="group-one">
+ PA6
+ </td>
+ </tr>
+
+ &lt;!&ndash; &#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45;&#45; &ndash;&gt;
+
+ <tr>
+ <td class="group-bottom">
+ TIM3_CH3
+ </td>
+ <td class="connection"></td>
+ <td class="group-bottom group-adc12">
+ ADC12_IN8
+ </td>
+ <td class="connection"></td>
+ <td>
+
+ </td>
+ <td class="connection"></td>
+ <td>
+ TIM1_CH2N (r)
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ PB0
+ </td>
+ </tr>
+ <tr>
+ <td class="connection" colspan="6"></td>
+ <td class="">
+ BOOT1
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ PB2
+ </td>
+ </tr>
+ <tr>
+ <td class="group-top group-tim1">
+ TIM1_BKIN
+ </td>
+ <td class="connection"></td>
+ <td class="group-i2c2">
+ I2C2_SMBAl
+ </td>
+ <td class="connection"></td>
+ <td class="group-top group-usart3">
+ USART3_CK
+ </td>
+ <td class="connection"></td>
+ <td class="group-top group-spi2">
+ SPI2_NSS
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ PB12
+ </td>
+ </tr>
+ <tr>
+ <td class="group-middle group-tim1">
+ TIM1_CH2N
+ </td>
+ <td class="connection" colspan="3"></td>
+ <td class="group-bottom">
+ USART3_RTS
+ </td>
+ <td class="connection"></td>
+ <td class="group-bottom">
+ SPI2_MISO
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ PB14
+ </td>
+ </tr>
+ <tr>
+ <td class="group-middle group-tim1">
+ TIM1_CH1
+ </td>
+ <td class="connection"></td>
+ <td class="">
+
+ </td>
+ <td class="connection"></td>
+ <td class="group-top group-usart1">
+ USART1_CK
+ </td>
+ <td class="connection"></td>
+ <td class="">
+ MCO
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ PA8
+ </td>
+ </tr>
+ <tr>
+ <td class="group-bottom group-tim1">
+ TIM1_CH3
+ </td>
+ <td class="connection"></td>
+ <td class="">
+
+ </td>
+ <td class="connection"></td>
+ <td class="group-bottom group-usart1">
+ USART1_RX
+ </td>
+ <td class="connection"></td>
+ <td class="">
+
+ </td>
+ <td class="connection"></td>
+ <td class="group-one">
+ PA10
+ </td>
+ </tr>
+ <tr>
+ <td class="connection" colspan="8"></td>
+ <td class="group-one">
+ GND
+ </td>
+ </tr>
+
+ &lt;!&ndash;
+ <tr>
+ <td>
+
+ </td>
+ <td>
+
+ </td>
+ <td>
+
+ </td>
+ <td>
+
+ </td>
+ </tr>
+ &ndash;&gt;
+</table>
+-->
+</body>
+</html>
diff --git a/html/tables.html b/html/tables.html
new file mode 100644
index 0000000..f005ef7
--- /dev/null
+++ b/html/tables.html
@@ -0,0 +1,80 @@
+<html>
+<head>
+ <style type="text/css">
+ #table2 {
+ /*border: 1px solid red;*/
+ /*
+ border-spacing: 10px;
+ */
+ /*border-collapse: collapse;*/
+ }
+
+ #table2 tr {
+ border: 1px solid blue;
+ }
+
+ #table2 td.t {
+ border: 1px inset green;
+ border-top-left-radius: 5px;
+ /*border-top-right-radius: 5px;*/
+ /*border-bottom: hidden;*/
+ }
+
+/*
+ #table2 td.m {
+ border: 1px solid green;
+ border-top: hidden;
+ border-bottom: hidden;
+ }
+*/
+ </style>
+ <style type="text/css">
+ #table1 {
+ border: 1px solid red;
+ border-spacing: 10px;
+ }
+
+ #table1 tr {
+ border: 1px solid blue;
+ }
+
+ #table1 td {
+ border: 1px solid green;
+ border-radius: 5px;
+ }
+ </style>
+</head>
+<body>
+<h4>Table 1</h4>
+<table id=table2>
+ <tr>
+ <td class="t">1.1</td>
+ </tr>
+ <tr>
+ <td class="m">2.1</td>
+ </tr>
+ <tr>
+ <td class="b">3.1</td>
+ </tr>
+</table>
+<hr>
+<table id=table1>
+ <tr>
+ <td>1.1</td>
+ <td>1.2</td>
+ <td>1.3</td>
+ </tr>
+ <tr>
+ <td>2.1</td>
+ <td>2.2</td>
+ <td>2.3</td>
+ </tr>
+ <tr>
+ <td>3.1</td>
+ <td>3.2</td>
+ <td>3.3</td>
+ </tr>
+</table>
+<hr>
+</body>
+</html>
diff --git a/playground/include/playground.h b/playground/include/playground.h
index 168c5c5..3e1b4bc 100644
--- a/playground/include/playground.h
+++ b/playground/include/playground.h
@@ -13,11 +13,34 @@ int main();
extern "C"
void Default_Handler();
+#include <cstdint>
+#include <limits>
+#include <utility>
+
// TODO: replace with std::extent<>; http://en.cppreference.com/w/cpp/types/extent
-template<typename T, size_t N>
+//template<typename T, std::size_t N>
+//static inline constexpr
+//std::size_t SizeOfArray(const T(&)[N]) {
+// return N;
+//}
+
+/*
+namespace {
+ template<class T> struct identity { using type = T; };
+}
+template<typename R, typename T, std::size_t N>
+static inline constexpr
+typename identity<R>::type SizeOfArray(const T(&)[N]) {
+ static_assert(std::numeric_limits<R>::max() >= N, "N does not fit in R");
+ return static_cast<R>(N);
+}
+*/
+
+template<typename R = std::size_t, typename T, std::size_t N>
static inline constexpr
-size_t SizeOfArray(const T(&)[N]) {
- return N;
+R SizeOfArray(const T(&)[N]) {
+ static_assert(std::numeric_limits<R>::max() >= N, "N does not fit in R");
+ return static_cast<R>(N);
}
#endif
diff --git a/playground/include/stm32f10x_conf.h b/playground/include/stm32f10x_conf.h
index f663d12..8c49c5e 100644
--- a/playground/include/stm32f10x_conf.h
+++ b/playground/include/stm32f10x_conf.h
@@ -30,7 +30,13 @@
#ifdef USE_FULL_ASSERT
#define assert_param(expr) ((expr) ? (void)0 : assert_failed((uint8_t *)__FILE__, __LINE__))
+#ifdef __cplusplus
+extern "C" {
+#endif
void assert_failed(uint8_t* file, uint32_t line);
+#ifdef __cplusplus
+}
+#endif
#else
#define assert_param(expr) ((void)0)
#endif