Hi,

Thanks you very much for all the answers.

Le 17/02/2025 à 02:18, NIIBE Yutaka a écrit :
Frédéric SUEL<[email protected]> wrote:
I find a new board made by WeAct Studio : Blue Pill Plus :

-- https://weactstudio.aliexpress.com/
Thank you for sharing information.  It's new for me.

*I test of gnuk 1.2.20 install on the board.*
[...]
      Is key-attributes for key generate on the card or determine the
type of key you can put on the card with keytocard command ?

      How to know witch keys Gnuk supports with keytocard command ?
It's an issue of UI of GnuPG.  UI of GnuPG is not (yet) kind enough to
inspect supported algorithm for key generation.  (GnuPG tries to
generate a key, asking a user.  There is no check.)

In newer OpenPGP card specifications, key attributes data object
(KEY-ATTR-INFO, in the term of gnupg/scd/app-openpgp.c) is introduced.
UI of GnuPG could use this data object, but it's not (yet) done.

We can inspect the data object, like (with Gnuk 2.2):

     $ gpg-connect-agent "scd getattr KEY-ATTR-INFO" /bye
     S KEY-ATTR-INFO OPENPGP.1 secp256k1
     S KEY-ATTR-INFO OPENPGP.1 ed25519
     S KEY-ATTR-INFO OPENPGP.1 ed448
     S KEY-ATTR-INFO OPENPGP.2 secp256k1
     S KEY-ATTR-INFO OPENPGP.2 cv25519
     S KEY-ATTR-INFO OPENPGP.2 cv448
     S KEY-ATTR-INFO OPENPGP.3 secp256k1
     S KEY-ATTR-INFO OPENPGP.3 ed25519
     S KEY-ATTR-INFO OPENPGP.3 ed448
     OK

*Led*

-----*
*

Led is slowly blinking (~ Off every two seconds for less than 1 second)

--------

Is it normal ? Can anyone explain to me the utility of this led ?
It's normal.  It shows status of CCID communication; Blinking means that
it's in use by scdaemon.

Now, it's clear for me.


*I also test of gnuk 2.2 install on the board.*
[...]
1) RSA support with key-attr is always available but doesn't work
2) I can't find with key-attr X448 or Ed448 support

As anyone explanations about this results ?
Are you sure if it's Gnuk 2.2?  As the CLI interaction example above
shows, it works for me (no RSA, has X448 and Ed448 support).

Yes, i made the test twice  (compiling and executing).

Environment : LinuxMint  21.3 / gnupg 2.4.4 (Ubuntu base) or ParrotOS (Debian base) / gnupg 2.2.40

-----

LinuxMint  21.3 (Ubuntu base) / gnupg 2.4.4

$ gpg --card-edit
can't connect to 'socket:///home/yokosano/.gnupg/log-socket': Aucun fichier ou dossier de ce nom

Reader ...........: 1209:2440:FSIJ-2.2-43112959:0
Application ID ...: D276000124010200FFFE431129590000
Application type .: OpenPGP
Version ..........: 2.0
Manufacturer .....: unmanaged S/N range
Serial number ....: 43112959
Name of cardholder: [non positionné]
Language prefs ...: [non positionné]
Salutation .......:
URL of public key : [non positionné]
Login data .......: [non positionné]
Signature PIN ....: forcé
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 1
KDF setting ......: on
UIF setting ......: Sign=off Decrypt=off Auth=off
Signature key ....: ADBB C781 90C0 36F8 6551  2D1D 6648 3F9B 33BA 0DE6
      created ....: 2025-02-15 19:32:10
Encryption key....: 9773 5974 62DE CA37 C49B  9722 2EDA 1B2F 4AD9 C893
      created ....: 2025-02-15 19:32:10
Authentication key: 8151 CC46 5948 B893 1538  3706 61F1 EDBE 7587 F428
      created ....: 2025-02-15 19:33:24
General key info..: [none]

gpg/carte> admin
Les commandes d'administration sont permises

gpg/carte> key-attr
Changing card key attribute for: Signature key
Sélectionnez le type de clef désiré :
   (1) RSA
   (2) ECC
Quel est votre choix ? 2
Sélectionnez le type de courbe elliptique désiré :
   (1) Curve 25519 *default*
   (4) NIST P-384
   (6) Brainpool P-256
Quel est votre choix ?
-----

ParrotOS (Debian base) / gnupg 2.2.40

$gpg --card-edit

Reader ...........: 1209:2440:FSIJ-2.2-43112959:0
Application ID ...: D276000124010200FFFE431129590000
Application type .: OpenPGP
Version ..........: 2.0
Manufacturer .....: unmanaged S/N range
Serial number ....: 43112959
Name of cardholder: [non positionné]
Language prefs ...: [non positionné]
Salutation .......:
URL of public key : [non positionné]
Login data .......: [non positionné]
Signature PIN ....: forcé
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 1
KDF setting ......: on
Signature key ....: ADBB C781 90C0 36F8 6551  2D1D 6648 3F9B 33BA 0DE6
      created ....: 2025-02-15 19:32:10
Encryption key....: 9773 5974 62DE CA37 C49B  9722 2EDA 1B2F 4AD9 C893
      created ....: 2025-02-15 19:32:10
Authentication key: 8151 CC46 5948 B893 1538  3706 61F1 EDBE 7587 F428
      created ....: 2025-02-15 19:33:24
General key info..:
pub  ed25519/0x66483F9B33BA0DE6 2025-02-15 tmtmt
sec>  ed25519/0x66483F9B33BA0DE6  créé : 2025-02-15  expire : 2065-02-05
                                  nº de carte : FFFE 43112959
ssb>  cv25519/0x2EDA1B2F4AD9C893  créé : 2025-02-15  expire : 2065-02-05
                                  nº de carte : FFFE 43112959
ssb>  ed25519/0x61F1EDBE7587F428  créé : 2025-02-15  expire : 2065-02-05
                                  nº de carte : FFFE 43112959

gpg/carte> admin
Les commandes d'administration sont permises

gpg/carte> key-attr
Changing card key attribute for: Signature key
Sélectionnez le type de clef désiré :
   (1) RSA
   (2) ECC
Quel est votre choix ? 2
Sélectionnez le type de courbe elliptique désiré :
   (1) Curve 25519
   (4) NIST P-384
Quel est votre choix ?

-----

Best regards
/* RFM : STM32F103x8 Référence Manual */

#define BOARD_NAME "BLUE-PILL-PLUS-CB" /* WeAct Studio stm32CBT6n there is a C8T6 version of this board */
/* http://https://stm32-base.org/boards/STM32F103C8T6-WeAct-Blue-Pill-Plus-Clone.html */
/* echo -n "BLUE-PILL-PLUS-CB" | shasum -a 256 | sed -e 's/^.*\(........\)  -$/\1/' */
#define BOARD_ID    0x1ba01477

#define MCU_STM32F1 1
#define STM32F10X_MD		/* Medium-density device */

#define STM32_PLLXTPRE                  STM32_PLLXTPRE_DIV1
#define STM32_PLLMUL_VALUE              9
#define STM32_HSECLK                    8000000

#define GPIO_LED_BASE   GPIOB_BASE
#define GPIO_LED_CLEAR_TO_EMIT          2
#define GPIO_USB_BASE   GPIOA_BASE
#undef  GPIO_OTHER_BASE

/*
 * Port A setup.
 * PA0  - input with pull-up: user button not used
 * PA0  - input with pull-up (TIM2_CH1): AN0 for NeuG
 * PA1  - input with pull-down (TIM2_CH2)
 * PA2  - input with pull-up (TIM2_CH3) connected to CIR module
 * PA3  - input with pull-up: external pin available to user
 * PA4  - Push pull output           (SPI1_NSS)
 * PA5  - Alternate Push pull output (SPI1_SCK)
 * PA6  - Alternate Push pull output (SPI1_MISO)
 * PA7  - Alternate Push pull output (SPI1_MOSI)
 * PA10 - Push pull output   (USB 1:ON 0:OFF) default 1
 * PA11 - Push Pull output 10MHz 0 default (until USB enabled) (USBDM)
 * PA12 - Push Pull output 10MHz 0 default (until USB enabled) (USBDP)
 * PAx  - input with pull-up
*/
#define VAL_GPIO_USB_ODR            0xFFFFE7FD
#define VAL_GPIO_USB_CRL            0xBBB38888      /*  PA7...PA0 */
#define VAL_GPIO_USB_CRH            0x88811888      /* PA15...PA8 */

/*
 * Port B setup
 * PB1  - input with pull-up: AN9 for NeuG
 * PB2  - Push pull output 50MHz (LED 1:ON 0:OFF)
 * ------------------------ Default
 * PBx  - input with pull-up.
*/
#define VAL_GPIO_LED_ODR            0xFFFFFFFF
#define VAL_GPIO_LED_CRL            0x88888388      /* GPIOB LOW  : PB7...PB0, all GPIO in input mod, except PB2 in output mod-50 Mhz => CNFy=00, MODy=11 in RFM */
#define VAL_GPIO_LED_CRH            0x88888888      /* GPIOB HIGH : PB15...PB8 en input mod,analog mode => CNFy=10, MODy=00 in RFM */

/* Enable GPIOA et GPIOB clocks (IOPxEN in RFM ) */
#define RCC_ENR_IOP_EN      (RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN)

/* Define APB2 peripheral reset register for IO port A et B (RCC_APB2RSTR in RFM) */
#define RCC_RSTR_IOP_RST    (RCC_APB2RSTR_IOPARST | RCC_APB2RSTR_IOPBRST)
#define BOARD_ID_CQ_STARM          0xc5480875
#define BOARD_ID_FST_01_00         0x613870a9
#define BOARD_ID_FST_01            0x696886af
#define BOARD_ID_FST_01G           0x8801277f
#define BOARD_ID_FST_01SZ          0x7e6fb084
#define BOARD_ID_MAPLE_MINI        0x7a445272
#define BOARD_ID_OLIMEX_STM32_H103 0xf92bb594
#define BOARD_ID_STBEE_MINI        0x1f341961
#define BOARD_ID_STBEE             0x945c37e8
#define BOARD_ID_STM32_PRIMER2     0x21e5798d
#define BOARD_ID_STM8S_DISCOVERY   0x2f0976bb
#define BOARD_ID_ST_DONGLE         0x2cd4e471
#define BOARD_ID_ST_NUCLEO_F103    0x9b87c16d
#define BOARD_ID_NITROKEY_START    0xad1e7ebd
#define BOARD_ID_GNUKEY_DS         0x67ee65a3
#define BOARD_ID_LONGAN_NANO       0xe65dace7
#define BOARD_ID_BLUE_PILL_PLUS_CB 0x1ba01477

extern const uint8_t sys_version[8];
#if defined(USE_SYS3) || defined(USE_SYS_BOARD_ID)
extern const uint32_t sys_board_id;
extern const uint8_t sys_board_name[];
# define SYS_BOARD_ID sys_board_id
#else
# define SYS_BOARD_ID BOARD_ID
#endif

typedef void (*handler)(void);
typedef void (*nonreturn_handler0)(void)__attribute__((noreturn));
typedef void (*nonreturn_handler1)(void *)__attribute__((noreturn));
extern handler vector[16];

static inline const uint8_t *
unique_device_id (void)
{
  /* STM32F103 has 96-bit unique device identifier */
  const uint8_t *addr = (const uint8_t *)0x1ffff7e8;

  return addr;
}

static inline void
set_led (int on)
{
  void (*func) (int) = (void (*)(int))vector[2];

  return (*func) (on);
}

static inline void
flash_unlock (void)
{
  (*vector[3]) ();
}

static inline int
flash_program_halfword (uintptr_t addr, uint16_t data)
{
  int (*func) (uintptr_t, uint16_t) = (int (*)(uintptr_t, uint16_t))vector[4];

  return (*func) (addr, data);
}

static inline int
flash_erase_page (uintptr_t addr)
{
  int (*func) (uintptr_t) = (int (*)(uintptr_t))vector[5];

  return (*func) (addr);
}

static inline int
flash_check_blank (const uint8_t *p_start, size_t size)
{
  int (*func) (const uint8_t *, int) = (int (*)(const uint8_t *, int))vector[6];

  return (*func) (p_start, size);
}

static inline int
flash_write (uintptr_t dst_addr, const uint8_t *src, size_t len)
{
  int (*func) (uintptr_t, const uint8_t *, size_t)
    = (int (*)(uintptr_t, const uint8_t *, size_t))vector[7];

  return (*func) (dst_addr, src, len);
}

static inline int
flash_protect (void)
{
  int (*func) (void) = (int (*)(void))vector[8];

  return (*func) ();
}

static inline void __attribute__((noreturn))
flash_erase_all_and_exec (void (*entry)(void))
{
  nonreturn_handler1 func = (nonreturn_handler1) vector[9] ;

  (*func) (entry);
}

static inline void
usb_lld_sys_init (void)
{
  (*vector[10]) ();
}

static inline void
usb_lld_sys_shutdown (void)
{
  (*vector[11]) ();
}

static inline void __attribute__((noreturn))
nvic_system_reset (void)
{
  nonreturn_handler0 func = (nonreturn_handler0)vector[12];

  (func) ();
}

#ifdef REQUIRE_CLOCK_GPIO_SETTING_IN_SYS
/* Provide the function entries.  */

static void __attribute__ ((used))
clock_init (void)
{
  (*vector[13]) ();
}

static void __attribute__ ((used))
gpio_init (void)
{
  (*vector[14]) ();
}
#endif
#! /bin/bash

# This is bash which supports ANSI-C Quoting
nl=$'\n'

#
# This file is *NOT* generated by GNU Autoconf, but written by NIIBE Yutaka
#
# Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2021,
#               2022
#               Free Software Initiative of Japan
#
# This file is a part of Gnuk, a GnuPG USB Token implementation.
#
# Gnuk 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 3 of the License, or
# (at your option) any later version.
#
# Gnuk 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.  If not, see <http://www.gnu.org/licenses/>.

#
# Submodule check
#
if ! test -f ../chopstx/rules.mk; then
  echo "Submodule 'chopstx' not found" >&2
  echo "You might need: git submodule update --init" >&2
  exit 1
fi

# Default settings
help=no
vidpid=none
target=FST_01
with_dfu=default
sys1_compat=yes
certdo=no
factory_reset=no
ackbtn_support=yes
flash_override=""
kdf_do=${kdf_do:-required}
# For emulation
prefix=/usr/local
exec_prefix='${prefix}'
libexecdir='${exec_prefix}/libexec'

# Revision number
if test -e ../.git; then
  if type git >/dev/null 2>&1; then
     REVISION=$(git describe --dirty="-modified")
  else
     # echo 'No git available, please install git'
     GIT_REVISION=$(sed -e 's/^\(.......\).*$/g\1/' "../.git/$(sed -e 's/^ref: 
//' ../.git/HEAD)")
     REVISION=$(cat ../VERSION)-$GIT_REVISION
  fi
else
  REVISION=$(cat ../VERSION)
fi

# Process each option
for option; do
  case $option in
  *=*)  optarg=$(expr "X$option" : '[^=]*=\(.*\)') ;;
  *)    optarg=yes ;;
  esac

  case $option in
  -h | --help)
    help=yes ;;
  --vidpid=*)
    vidpid=$optarg ;;
  --target=*)
    target=$optarg ;;
  --enable-certdo)
    certdo=yes ;;
  --disable-certdo)
    certdo=no ;;
  --enable-sys1-compat)
    sys1_compat=yes ;;
  --disable-sys1-compat)
    sys1_compat=no ;;
  --enable-factory-reset)
    factory_reset=yes ;;
  --disable-factory-reset)
    factory_reset=no ;;
  --with-dfu)
    with_dfu=yes ;;
  --without-dfu)
    with_dfu=no ;;
  #
  # For emulation
  #
  --prefix=*)
    prefix=optarg ;;
  --exec-prefix=*)
    exec_prefix=optarg ;;
  --libexecdir=*)
    libexecdir=optarg ;;
  *)
    echo "Unrecognized option \`$option'" >&2
    echo "Try \`$0 --help' for more information." >&2
    exit 1
    ;;
  esac
done

if test "$help" = "yes"; then
  cat <<EOF
Usage: $0 [OPTION]...

Defaults for the options are specified in brackets.

Configuration:
  -h, --help            display this help and exit      [no]
  --vidpid=VID:PID      specify vendor/product ID       [<NONE>]
  --target=TARGET       specify target                  [FST_01]
                        supported targets are:
                           FST_01
                           FST_01G
                           FST_01SZ
                           OLIMEX_STM32_H103
                           MAPLE_MINI
                           ST_DONGLE
                           ST_NUCLEO_F103
                           NITROKEY_START
                           BLUE_PILL
                           STM8S_DISCOVERY
                           CQ_STARM
                           STM32_PRIMER2
                           STBEE
                           STBEE_MINI
                           BLUE_PILL_PLUS_CB
                           FST_01_00 (unreleased version with 8MHz XTAL)
  --enable-factory-reset
                        support life cycle management   [no]
  --enable-certdo       support CERT.3 data object      [no]
  --enable-sys1-compat  enable SYS 1.0 compatibility    [yes]
                           executable is target dependent
  --disable-sys1-compat disable SYS 1.0 compatibility   [no]
                           executable is target independent
                           but requires SYS 2.0 or newer
  --with-dfu            build image for DFU             [<target specific>]
EOF
  exit 0
fi

BOARD_HEADER_FILE=board-$(echo $target | tr '_[:upper:]' '-[:lower:]').h
echo "Header file is: $BOARD_HEADER_FILE"
ln -sf "../chopstx/board/$BOARD_HEADER_FILE" board.h

# Frequency
MHZ=72
# Flash page size in byte
FLASH_PAGE_SIZE=1024
# Flash memory size in KiB
FLASH_SIZE=128
# Memory size in KiB
MEMORY_SIZE=20

# Settings for TARGET
case $target in
BLUE_PILL|STM8S_DISCOVERY)
  # It's 64KB version of STM32F103, but actually has 128KB
  flash_override="-DSTM32F103_OVERRIDE_FLASH_SIZE_KB=128"
  ;;
CQ_STARM|STBEE_MINI)
  if test "$with_dfu" = "default"; then
    with_dfu=yes;
  fi  ;;
STM32_PRIMER2)
  FLASH_PAGE_SIZE=2048
  FLASH_SIZE=512
  MEMORY_SIZE=64
  ;;
STBEE)
  FLASH_PAGE_SIZE=2048
  FLASH_SIZE=512
  MEMORY_SIZE=64
  if test "$with_dfu" = "default"; then
    with_dfu=yes;
  fi  ;;
BLUE_PILL_G)
  MHZ=96
  ;;
FST_01SZ)
  MHZ=96
  ;;
*)
  ;;
esac

def_mhz="-DMHZ=$MHZ"
if test "$target" = "GNU_LINUX"; then
  ldscript=""
  chip="gnu-linux"
  arch="gnu-linux"
  emulation="yes"
  cross=""
  mcu="none"
  def_emulation="-DGNU_LINUX_EMULATION"
  def_memory_size="-DMEMORY_SIZE=1024"
  enable_hexoutput=""
  libs="-lpthread"
else
  ldscript="gnuk.ld"
  chip="stm32f103"
  arch="cortex-m"
  emulation=""
  cross="arm-none-eabi-"
  mcu="cortex-m3"
  def_emulation=""
  def_memory_size="-DMEMORY_SIZE=$MEMORY_SIZE"
  enable_hexoutput=yes
  libs=""
fi

if test "$emulation" = "yes"; then
  if test "$vidpid" = "none"; then
    vidpid=0000:0000
  else
    echo "Please don't specify VID:PID for emulation at compile time;"
    echo "It is a user who should specify VID:PID at run time."
    exit 1
  fi
else
  if test "$vidpid" = "none"; then
    echo "Please specify Vendor ID and Product ID by --vidpid option." >&2
  exit 1
  fi
fi

ORIGIN_REAL=0x08000000
ORIGIN_REAL_DEFINE="#define ORIGIN_REAL $ORIGIN_REAL"
# --with-dfu option
if test "$with_dfu" = "yes"; then
  if test "$target" = "FST_01" -o "$target" = "FST_01G" \
     -o "$target" = "FST_01_00"; then
      echo "FST-01 doesn't have DFU loader, you should not use --with-dfu." >&2
      exit 1
  fi
  echo "Configured for DFU"
  if test "$target" = "MAPLE_MINI"; then
    # Note that the default bootloader is too large, need for instance
    # STM32duino for DFU on Maple Mini
    ORIGIN=0x08002000
    FLASH_SIZE=$((FLASH_SIZE - 8))
  else
    ORIGIN=0x08003000
    FLASH_SIZE=$((FLASH_SIZE - 12))
  fi
  DFU_DEFINE="#define DFU_SUPPORT 1"
else
  with_dfu=no
  echo "Configured for bare system (no-DFU)"
  ORIGIN=${ORIGIN_REAL}
  DFU_DEFINE="#undef DFU_SUPPORT"
fi
ORIGIN_DEFINE="#define ORIGIN $ORIGIN"

# --enable-certdo option
if test "$certdo" = "yes"; then
  CERTDO_DEFINE="#define CERTDO_SUPPORT 1"
  echo "CERT.3 Data Object is supported"
else
  CERTDO_DEFINE="#undef CERTDO_SUPPORT"
  echo "CERT.3 Data Object is NOT supported"
fi

# --enable-factory-reset option
if test "$factory_reset" = "yes"; then
  LIFE_CYCLE_MANAGEMENT_DEFINE="#define LIFE_CYCLE_MANAGEMENT_SUPPORT 1"
  echo "Life cycle management is supported"
else
  LIFE_CYCLE_MANAGEMENT_DEFINE="#undef LIFE_CYCLE_MANAGEMENT_SUPPORT"
  echo "Life cycle management is NOT supported"
fi

# Acknowledge button support
if test "$ackbtn_support" = "yes"; then
  ACKBTN_DEFINE="#define ACKBTN_SUPPORT 1"
  echo "Acknowledge button is supported"
else
  ACKBTN_DEFINE="#undef ACKBTN_SUPPORT"
  echo "Acknowledge button is not supported"
fi

# KDF Data Object is always required for GNU/Linux emulation
if test "$kdf_do" = "required"; then
  KDF_DO_REQUIRED_DEFINE="#define KDF_DO_REQUIRED 1"
  echo "KDF DO is required before key import/generation"
else
  KDF_DO_REQUIRED_DEFINE="#undef KDF_DO_REQUIRED"
fi

### !!! Replace following string of "FSIJ" to yours !!! ####
SERIALNO="FSIJ-$(sed -e 's%^[^/]*/%%' <../VERSION)-"

SERIALNO_STR_LEN_DEFINE="#define SERIALNO_STR_LEN ${#SERIALNO}"


if test "$sys1_compat" = "yes"; then
  
CONFIG="$target:dfu=$with_dfu:certdo=$certdo:factory_reset=$factory_reset:kdf=$kdf_do"
else
  if test "$with_dfu" = "yes"; then
    echo "Common binary can't support DFU loader, don't use --with-dfu." >&2
    exit 1
  fi
  # Override settings for common binary.  Safer side.
  FLASH_PAGE_SIZE=2048
  FLASH_SIZE=128
  MEMORY_SIZE=20
  CONFIG="common:certdo=$certdo:factory_reset=$factory_reset:kdf=$kdf_do"
fi

output_vid_pid_version () {
  echo "$VIDPID" | \
  sed -n -e 
"s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\):\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$%\1\t\2\t\3\t\4%p"
 | \
  while read -r FIRST SECOND THIRD FOURTH; do
    if test $FIRST != 00; then
      echo replace_vid_msb $FIRST
    fi
    if test $SECOND != 00; then
      echo replace_vid_lsb $SECOND
    fi
    if test $THIRD != 00; then
      echo replace_pid_msb $THIRD
    fi
    if test $FOURTH != 00; then
      echo replace_pid_lsb $FOURTH
    fi
  done
  echo "$VERSION" | \
  sed -n -e "s%^\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)$%\1\t\2%p" | \
  while read -r FIRST SECOND; do
    if test $FIRST != 00; then
      echo replace_bcd_device_msb $FIRST
    fi
    if test $SECOND != 00; then
      echo replace_bcd_device_lsb $SECOND
    fi
  done
}

output_vendor_product_serial_strings () {
  name=$1

  echo "static const uint8_t ${name}string_vendor[] = {"
  echo "  ${#VENDOR}*2+2,                       /* bLength */"
  echo "  STRING_DESCRIPTOR,            /* bDescriptorType */"
  echo "  /* Manufacturer: \"$VENDOR\" */"
  echo "$VENDOR" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e 
"s/\(.\)/'\1', 0, /g" -e "s/^/  /" -e "/^  ./s/ $//p"
  echo '};'
  echo
  echo "static const uint8_t ${name}string_product[] = {"
  echo "  ${#PRODUCT}*2+2,                      /* bLength */"
  echo "  STRING_DESCRIPTOR,            /* bDescriptorType */"
  echo "  /* Product name: \"$PRODUCT\" */"
  echo "$PRODUCT" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e 
"s/\(.\)/'\1', 0, /g" -e "s/^/  /" -e "/^  ./s/ $//p"
  echo '};'

  if test -n "$name"; then
  echo
  echo "const uint8_t ${name}string_serial[] = {"
  echo "  ${#SERIALNO}*2+2+16,                  /* bLength */"
  echo "  STRING_DESCRIPTOR,            /* bDescriptorType */"
  echo "  /* Serial number: \"$SERIALNO\" */"
  echo "$SERIALNO" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e 
"s/\(.\)/'\1', 0, /g" -e "s/^/  /" -e "/^  ./s/ $//p"
  if test "$emulation" = "yes"; then
    echo "  'E', 0, 'M', 0, 'U', 0, 'L', 0,"
    echo "  'A', 0, 'T', 0, 'E', 0, 'D', 0,"
  else
    echo "  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
    echo "  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,"
  fi
  echo '};'
  echo
  echo '#ifdef USB_STRINGS_FOR_GNUK'
  echo "static const uint8_t ${name}revision_detail[] = {"
  echo "  ${#REVISION}*2+2,                     /* bLength */"
  echo "  STRING_DESCRIPTOR,            /* bDescriptorType */"
  echo "  /* revision detail: \"$REVISION\" */"
  echo "$REVISION" | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e 
"s/\(.\)/'\1', 0, /g" -e "s/^/  /" -e "/^  ./s/ $//p"
  echo '};'
  echo
  echo "static const uint8_t ${name}config_options[] = {"
  echo "  ${#CONFIG}*2+2,                       /* bLength */"
  echo "  STRING_DESCRIPTOR,            /* bDescriptorType */"
  echo "  /* configure options: \"$CONFIG\" */"
  echo $CONFIG | sed -e "s/\(........\)/\1\\${nl}/g" | sed -n -e "s/\(.\)/'\1', 
0, /g" -e "s/^/  /" -e "/^  ./s/ $//p"
  echo '};'
  echo '#endif'
  fi
}

(echo "#! /bin/bash"
 echo
 echo 'source "binary-edit.sh"') > put-vid-pid-ver.sh

if !(IFS="      "
  while read -r VIDPID VERSION PRODUCT VENDOR; do
    if test "$vidpid" = "$VIDPID"; then
      echo                       >> put-vid-pid-ver.sh
      echo 'addr=$file_off_ADDR' >> put-vid-pid-ver.sh
      output_vid_pid_version     >> put-vid-pid-ver.sh
      output_vendor_product_serial_strings gnuk_ >usb-strings.c.inc
      exit 0
    fi
  done; exit 1) < ../GNUK_USB_DEVICE_ID
then
  echo "Please specify valid Vendor ID and Product ID." >&2
  echo "Check ../GNUK_USB_DEVICE_ID." >&2
  exit 1
fi

if test "$sys1_compat" = "no"; then
    # Disable when you are sure that it's sys version 3.0 or later.
    # Note that Gnuk 1.0 and NeuG (until 0.06) uses sys version 1.0.
    # Disabling the compatibility, executable will be target independent,
    # assuming the clock initialization will be done by clock_init in 
    # SYS.
    use_sys3="-DUSE_SYS3"
else
    use_sys3=""
fi


(echo "CHIP=$chip";
 echo "ARCH=$arch";
 echo "EMULATION=$emulation";
 echo "CROSS=$cross";
 echo "MCU=$mcu";
 echo "DEFS=$use_sys3 $flash_override $def_emulation $def_memory_size $def_mhz";
 echo "LDSCRIPT=$ldscript";
 echo "LIBS=$libs";
 echo "ENABLE_FRAUCHEKY=$enable_fraucheky";
 echo "ENABLE_OUTPUT_HEX=$enable_hexoutput"
 if test "$ackbtn_support" = "yes"; then
   echo "USE_ACKBTN=yes"
 fi
 if test "$with_dfu" = "yes"; then
   echo "USE_DFU=yes"
 fi
 if test "$emulation" = "yes"; then
   echo "prefix=$prefix"
   echo "exec_prefix=$exec_prefix"
   echo "libexecdir=$libexecdir"
 fi
)       > config.mk

if test "$certdo" = "yes"; then
  sed -e "/^@CERTDO_SUPPORT_START@$/ d" -e "/^@CERTDO_SUPPORT_END@$/ d" \
      -e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \
      -e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
      -e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
        < gnuk.ld.in > gnuk.ld
else
  sed -e "/^@CERTDO_SUPPORT_START@$/,/^@CERTDO_SUPPORT_END@$/ d" \
      -e "s/@ORIGIN@/$ORIGIN/" -e "s/@FLASH_SIZE@/$FLASH_SIZE/" \
      -e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
      -e "s/@FLASH_PAGE_SIZE@/$FLASH_PAGE_SIZE/" \
        < gnuk.ld.in > gnuk.ld
fi
sed -e "s/@ORIGIN_REAL@/$ORIGIN_REAL/" -e "s/@MEMORY_SIZE@/$MEMORY_SIZE/" \
        < stdaln-sys.ld.in > stdaln-sys.ld
sed -e "s/@DFU_DEFINE@/$DFU_DEFINE/" \
    -e "s/@ORIGIN_DEFINE@/$ORIGIN_DEFINE/" \
    -e "s/@ORIGIN_REAL_DEFINE@/$ORIGIN_REAL_DEFINE/" \
    -e "s/@CERTDO_DEFINE@/$CERTDO_DEFINE/" \
    -e "s/@LIFE_CYCLE_MANAGEMENT_DEFINE@/$LIFE_CYCLE_MANAGEMENT_DEFINE/" \
    -e "s/@ACKBTN_DEFINE@/$ACKBTN_DEFINE/" \
    -e "s/@SERIALNO_STR_LEN_DEFINE@/$SERIALNO_STR_LEN_DEFINE/" \
    -e "s/@KDF_DO_REQUIRED_DEFINE@/$KDF_DO_REQUIRED_DEFINE/" \
        < config.h.in > config.h
exit 0
/*
 * adc_stm32f103.c - ADC driver for STM32F103
 *                   In this ADC driver, there are NeuG specific parts.
 *                   You need to modify to use this as generic ADC driver.
 *
 * Copyright (C) 2011, 2012, 2013, 2015, 2016, 2017, 2018
 *               Free Software Initiative of Japan
 * Author: NIIBE Yutaka <[email protected]>
 *
 * This file is a part of Chopstx, a thread library for embedded.
 *
 * Chopstx 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 3 of the License, or
 * (at your option) any later version.
 *
 * Chopstx 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.  If not, see <http://www.gnu.org/licenses/>.
 *
 * As additional permission under GNU GPL version 3 section 7, you may
 * distribute non-source form of the Program without the copy of the
 * GNU GPL normally required by section 4, provided you inform the
 * recipients of GNU GPL by a written offer.
 *
 */

#include <stdint.h>
#include <stdlib.h>
#include <chopstx.h>
#include <mcu/stm32f103.h>
#include "adc.h"
#include "board.h"
#include "sys.h"

#define STM32_ADC_ADC1_DMA_PRIORITY         2

#define ADC_SMPR1_SMP_VREF(n)   ((n) << 21)
#define ADC_SMPR1_SMP_SENSOR(n) ((n) << 18)

#define ADC_SMPR1_SMP_AN10(n)   ((n) << 0)
#define ADC_SMPR1_SMP_AN11(n)   ((n) << 3)

#define ADC_SMPR2_SMP_AN0(n)    ((n) << 0)
#define ADC_SMPR2_SMP_AN1(n)    ((n) << 3)
#define ADC_SMPR2_SMP_AN2(n)    ((n) << 6)
#define ADC_SMPR2_SMP_AN3(n)    ((n) << 9)
#define ADC_SMPR2_SMP_AN8(n)    ((n) << 24)
#define ADC_SMPR2_SMP_AN9(n)    ((n) << 27)

#define ADC_SQR1_NUM_CH(n)      (((n) - 1) << 20)

#define ADC_SQR3_SQ1_N(n)       ((n) << 0)
#define ADC_SQR3_SQ2_N(n)       ((n) << 5)
#define ADC_SQR3_SQ3_N(n)       ((n) << 10)
#define ADC_SQR3_SQ4_N(n)       ((n) << 15)

#define ADC_SAMPLE_1P5          0

#define ADC_CHANNEL_IN0         0
#define ADC_CHANNEL_IN1         1
#define ADC_CHANNEL_IN2         2
#define ADC_CHANNEL_IN3         3
#define ADC_CHANNEL_IN8         8
#define ADC_CHANNEL_IN9         9
#define ADC_CHANNEL_IN10        10
#define ADC_CHANNEL_IN11        11
#define ADC_CHANNEL_SENSOR      16
#define ADC_CHANNEL_VREFINT     17

#define DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
#ifndef MCU_STM32F1_GD32F1
#define DELIBARATELY_DO_IT_WRONG_START_STOP
#endif

#ifdef DELIBARATELY_DO_IT_WRONG_VREF_SAMPLE_TIME
#define ADC_SAMPLE_VREF ADC_SAMPLE_1P5
#define ADC_SAMPLE_SENSOR ADC_SAMPLE_1P5
#else
#define ADC_SAMPLE_VREF ADC_SAMPLE_239P5
#define ADC_SAMPLE_SENSOR ADC_SAMPLE_239P5
#endif

#define NEUG_DMA_CHANNEL STM32_DMA1_STREAM1
#define NEUG_DMA_MODE							\
  (  STM32_DMA_CR_PL (STM32_ADC_ADC1_DMA_PRIORITY)			\
     | STM32_DMA_CR_MSIZE_WORD | STM32_DMA_CR_PSIZE_WORD		\
     | STM32_DMA_CR_MINC       | STM32_DMA_CR_TCIE			\
     | STM32_DMA_CR_TEIE  )

#define NEUG_ADC_SETTING1_SMPR1 ADC_SMPR1_SMP_VREF(ADC_SAMPLE_VREF)     \
                              | ADC_SMPR1_SMP_SENSOR(ADC_SAMPLE_SENSOR)
#define NEUG_ADC_SETTING1_SMPR2 0
#define NEUG_ADC_SETTING1_SQR3  ADC_SQR3_SQ1_N(ADC_CHANNEL_VREFINT)     \
                              | ADC_SQR3_SQ2_N(ADC_CHANNEL_SENSOR)      \
                              | ADC_SQR3_SQ3_N(ADC_CHANNEL_SENSOR)      \
                              | ADC_SQR3_SQ4_N(ADC_CHANNEL_VREFINT)
#define NEUG_ADC_SETTING1_NUM_CHANNELS 4

/*
 * ADC finish interrupt
 */
#ifdef MCU_GD32VF1
#define INTR_REQ_DMA1_Channel1 30
#else
#define INTR_REQ_DMA1_Channel1 11
#endif

static chopstx_intr_t adc_intr;

/*
 * Do calibration for both of ADCs.
 */
int
adc_init (void)
{
  RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
  RCC->APB2RSTR = (RCC_APB2RSTR_ADC1RST | RCC_APB2RSTR_ADC2RST);
  RCC->APB2RSTR = 0;

  ADC1->CR1 = 0;
  ADC1->CR2 = ADC_CR2_ADON;
  chopstx_usec_wait (1000);

  ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
  while ((ADC1->CR2 & ADC_CR2_RSTCAL) != 0)
    ;
  ADC1->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
  while ((ADC1->CR2 & ADC_CR2_CAL) != 0)
    ;
  ADC1->CR2 = 0;

  ADC2->CR1 = 0;
  ADC2->CR2 = ADC_CR2_ADON;
  chopstx_usec_wait (1000);

  ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_RSTCAL;
  while ((ADC2->CR2 & ADC_CR2_RSTCAL) != 0)
    ;
  ADC2->CR2 = ADC_CR2_ADON | ADC_CR2_CAL;
  while ((ADC2->CR2 & ADC_CR2_CAL) != 0)
    ;
  ADC2->CR2 = 0;
  RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);

  chopstx_claim_irq (&adc_intr, INTR_REQ_DMA1_Channel1);
  return 0;
}

static void
get_adc_config (uint32_t config[4])
{
  config[2] = ADC_SQR1_NUM_CH(2);
  switch (SYS_BOARD_ID)
    {
    case BOARD_ID_FST_01G:
    case BOARD_ID_FST_01:
      config[0] = 0;
      config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
		| ADC_SMPR2_SMP_AN9(ADC_SAMPLE_1P5);
      config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
		| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN9);
      break;

    case BOARD_ID_OLIMEX_STM32_H103:
    case BOARD_ID_STBEE:
      config[0] = ADC_SMPR1_SMP_AN10(ADC_SAMPLE_1P5)
		| ADC_SMPR1_SMP_AN11(ADC_SAMPLE_1P5);
      config[1] = 0;
      config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN10)
		| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN11);
      break;

    case BOARD_ID_STBEE_MINI:
      config[0] = 0;
      config[1] = ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5)
		| ADC_SMPR2_SMP_AN2(ADC_SAMPLE_1P5);
      config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN1)
		| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN2);
      break;

    case BOARD_ID_ST_NUCLEO_F103:
      config[0] = 0;
      config[1] = ADC_SMPR2_SMP_AN8(ADC_SAMPLE_1P5)
		| ADC_SMPR2_SMP_AN9(ADC_SAMPLE_1P5);
      config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN8)
		| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN9);
      break;

    case BOARD_ID_LONGAN_NANO:
      config[0] = 0;
      config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
		| ADC_SMPR2_SMP_AN3(ADC_SAMPLE_1P5);
      config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
		| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN3);
      break;

    case BOARD_ID_CQ_STARM:
    case BOARD_ID_FST_01_00:
    case BOARD_ID_MAPLE_MINI:
    case BOARD_ID_STM32_PRIMER2:
    case BOARD_ID_STM8S_DISCOVERY:
    case BOARD_ID_ST_DONGLE:
    case BOARD_ID_NITROKEY_START:
    case BOARD_ID_FST_01SZ:
    case BOARD_ID_BLUE_PILL_PLUS_CB:
    default:
      config[0] = 0;
      config[1] = ADC_SMPR2_SMP_AN0(ADC_SAMPLE_1P5)
		| ADC_SMPR2_SMP_AN1(ADC_SAMPLE_1P5);
      config[3] = ADC_SQR3_SQ1_N(ADC_CHANNEL_IN0)
		| ADC_SQR3_SQ2_N(ADC_CHANNEL_IN1);
      break;
    }
}


void
adc_start (void)
{
  uint32_t config[4];

  get_adc_config (config);

  /* Use DMA channel 1.  */
  RCC->AHBENR |= RCC_AHBENR_DMA1EN;
  DMA1_Channel1->CCR = STM32_DMA_CCR_RESET_VALUE;
  DMA1->IFCR = 0xffffffff;

  RCC->APB2ENR |= (RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);

  ADC1->SMPR1 = NEUG_ADC_SETTING1_SMPR1;
  ADC1->SMPR2 = NEUG_ADC_SETTING1_SMPR2;
  ADC1->SQR1 = ADC_SQR1_NUM_CH(NEUG_ADC_SETTING1_NUM_CHANNELS);
  ADC1->SQR2 = 0;
  ADC1->SQR3 = NEUG_ADC_SETTING1_SQR3;
  ADC1->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
	       | ADC_CR1_SCAN);
  ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
	       | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
  chopstx_usec_wait (1000);

  ADC2->SMPR1 = config[0];
  ADC2->SMPR2 = config[1];
  ADC2->SQR1 = config[2];
  ADC2->SQR2 = 0;
  ADC2->SQR3 = config[3];
  ADC2->CR1 = (ADC_CR1_DUALMOD_2 | ADC_CR1_DUALMOD_1 | ADC_CR1_DUALMOD_0
	       | ADC_CR1_SCAN);
  ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
  chopstx_usec_wait (1000);

#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
  /*
   * We could just let ADC run continuously always and only enable DMA
   * to receive stable data from ADC.  But our purpose is not to get
   * correct data but noise.  In fact, we can get more noise when we
   * start/stop ADC each time.
   */
  ADC2->CR2 = 0;
  ADC1->CR2 = 0;
#else
  /* Start conversion.  */
  ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
  ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
	       | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
#endif
}

uint32_t adc_buf[64];

void
adc_start_conversion (int offset, int count)
{
  DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;        /* SetPeripheral */
  DMA1_Channel1->CMAR = (uint32_t)&adc_buf[offset]; /* SetMemory0    */
  DMA1_Channel1->CNDTR = count;                     /* Counter       */
  DMA1_Channel1->CCR = NEUG_DMA_MODE | DMA_CCR1_EN; /* Mode   */

#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
  /* Power on */
  ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
  ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
	       | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
  /*
   * Start conversion.  tSTAB is 1uS, but we don't follow the spec, to
   * get more noise.
   */
  ADC2->CR2 = ADC_CR2_EXTTRIG | ADC_CR2_CONT | ADC_CR2_ADON;
  ADC1->CR2 = (ADC_CR2_TSVREFE | ADC_CR2_EXTTRIG | ADC_CR2_SWSTART
	       | ADC_CR2_EXTSEL | ADC_CR2_DMA | ADC_CR2_CONT | ADC_CR2_ADON);
#endif
}


static void adc_stop_conversion (void)
{
  DMA1_Channel1->CCR &= ~DMA_CCR1_EN;

#ifdef DELIBARATELY_DO_IT_WRONG_START_STOP
  ADC2->CR2 = 0;
  ADC1->CR2 = 0;
#endif
}

void
adc_stop (void)
{
  ADC1->CR1 = 0;
  ADC1->CR2 = 0;

  ADC2->CR1 = 0;
  ADC2->CR2 = 0;

  RCC->AHBENR &= ~RCC_AHBENR_DMA1EN;
  RCC->APB2ENR &= ~(RCC_APB2ENR_ADC1EN | RCC_APB2ENR_ADC2EN);
}


static uint32_t adc_err;

/*
 * Return 0 on success.
 * Return 1 on error.
 */
int
adc_wait_completion (void)
{
  uint32_t flags;

  while (1)
    {
      chopstx_intr_wait (&adc_intr);
      flags = DMA1->ISR & STM32_DMA_ISR_MASK; /* Channel 1 interrupt cause.  */
      /*
       * Clear interrupt cause of channel 1.
       *
       * Note that CGIFx=0, as CGIFx=1 clears all of GIF, HTIF, TCIF
       * and TEIF.
       */
      DMA1->IFCR = (flags & ~1);
      chopstx_intr_done (&adc_intr);

      if ((flags & STM32_DMA_ISR_TEIF) != 0)  /* DMA errors  */
	{
	  /* Should never happened.  If any, it's coding error. */
	  /* Access an unmapped address space or alignment violation.  */
	  adc_err++;
	  adc_stop_conversion ();
	  return 1;
	}
      else if ((flags & STM32_DMA_ISR_TCIF) != 0) /* Transfer complete */
	{
	  adc_stop_conversion ();
	  return 0;
	}
    }
}
_______________________________________________
Gnuk-users mailing list
[email protected]
https://lists.gnupg.org/mailman/listinfo/gnuk-users

Reply via email to