STM32のクロック系について

今頃気づいたのかという話ですが、STM32のクロック系にはPLLがあるので、任意の周波数にアップコンバートできます、従ってST-Linkの水晶発振器を使ってそれを基準周波数に使えば(Nucleoを切り離さない限り)、安定したクロックになります

で、ST-Linkの水晶使って最大動作周波数に設定した時のコンフィグは以下の通り

前の記事、

https://isehara-3lv.sakura.ne.jp/blog/wp-admin/post.php?post=5082&action=edit

ではこういうコンフィグ

従ってペリフェラルだけじゃなくて、MCUやDMAのクロックまで落とされていました

ちなみにこの状態でADCのCounter Settingを変更して前回と同じサンプリング周波数(10KHz)にした時の実行時間は、

なぜ時間測定がクロック周波数変えても変わらないのか疑問に思いましたが、以下のコードに見るようにクロック周波数は時間の分解能を決めてはいますが、経過時間には無縁だから

float getTimeUs(uint32_t count)
{
  float us = 1000000 * (float)count / (float)SystemCoreClock;
  return us;
}

前回の実行時間は12,829μsだったので微妙に速くなっています、DMA中の処理時間は見えてこない(8MHzで間に合ってしまう)だろうから、それ以外の前後のMCUの処理時間の84MHzと8MHzのクロック周波数の差分だろうと思います

クロックの種類がたくさんありますが、大きく用途ごとに分類すると、

・HCLK:MCU周りのバスクロック

・FCLK:MCUのコアクロック

・APB1:peripheralは低速の周辺デバイスI2C, USART2/3, SPI2/3, CAN, PWR などで最大42MHz、timer clockはTim2~7用

・APB2:APB1より高速の周辺デバイス用でTIM1, ADC, GPIOなど、timer clockは相対的に高速なTim1用

 

admin

ADCの変換タイミングを外部(Timer)で決めてやる

時間測定が、

STM32での実行時間測定(DWT機能を使う)

でできるようになったので、次は今までfree runだったADCとDMA転送に対してADCの変換タイミングをTimerで決めてやることにします

ただ、この場合に内部のRC発信器使うのでは精度も安定性も確保できないので、幸いNucleoではST-Linkボード上の水晶発信器(8MHz)を取り込むことが可能なので、その信号を基準値として使います

<実行環境>

・M4 MacBook Pro Tahoe

・CubeIDE 1.19.0

・STM32F401re

 

<まずはペリフェラルクロックだけ変えてみた:これ間違い、次の記事でクロック系を記述>

クロックの切り替えは単純でMXのClock Configulationの設定を変えるだけ、System Clock MultiplexerでHSIからHSEを選択するだけ

ちなみにこの状態で同じ条件(128ワードのDMA転送実施)すると、HSI使ってたときにはおよそ94μsが、

504μsに変化、system clockは変化してないのでDMA転送とかは高速のままだろうから10倍遅くはならない

 

<ADCの変換タイミングにtimer 3を使う>

timer2は時間測定用に使っているのでTGO(ADCにトリガーかける機能)があるtimer3を使う

・ADCの設定

変換タイミングExternal Trigger ConversionをTimer3のTGOにするのと、後で述べますがContinuous Conversion ModeをDisabledにするのが大切

 

・Timer3の設定(サンプリング周期を10KHzにするようにしたのとADCの起動用にTrigger Event SelectionをUpdate Eventにする)

・ソースコード(該当部分)

ADCスタートするのと合わせてtimer3もスタートする

 

<実行結果>

なんか変だよね、これが先ほどのContinuous Conversion ModeをDisabledと関連していて、ADCにタイマーで変換タイミング作ってもADCのMXで以下の設定変更しないと機能しない

Continuous Conversion = Disable

実はタイマーでサンプリング周期決めたいのに、これがEnableだと以降のタイマートリガは無視してADCは勝手に変換実行してDMA転送してしまうからこのような値になった訳

でDisableにすると、

128wordsで100μs間隔のサンプリングだと、これで正しい

STM32は多機能で設定次第で如何様にも動作させられるから、それゆえはまりどころも多いということ

 

admin

STM32での実行時間測定(DWT機能を使う)

これもデバッグ時にはほぼ必須の機能である実行時間の測定方法についてです

STM32 タイマーを使って処理時間を計測する

を使ってみました、DWT機能というのはData Watchpoint and Trace Unitの略でArm Mコアで正確な時間測定を行う時に使われる機能のようです

<動作環境>

・M4 MacBook Pro Tahoe

・CubeIDE 1.19.0

・STM32F401re

<セットアップ>

例にあるDWT.hとDWT.cというファイルを作成してそれぞれ、Core / IncとCore / Src以下に配置します

https://isehara-3lv.sakura.ne.jp/blog/2025/12/05/adcをdma転送で実行してみる/

の記事のコードに追加してADCのDMA転送の時間を測定してみました

タイマーの初期化処理は、

__IO表記はC言語におけるvolatileのalias表記です

ソースコードはこんな感じ、最初if文の直後においてましたが、測定結果が複数回実行しても変わらないので、cnt++行の後に移動して結果と比較

<実行結果>

最初のコードでの実行時間

ログポイントをずらした結果

確かに差分で0.1μsぐらい増加してますね

この時間がどう決まるかというと、DMAで128words転送しているので、一回あたりおよそ0.73μs、MXの設定でADC_Resolution設定のサンプリング間隔(TSMP = 15 ADC cycles)、クロック84/4 MHzだと0.71μsだからほぼ一致、という計算でいいのかな

時間測定としてこの方法は多少の細工は必要ですが、測定結果は正確であるように思います

 

admin

CubeIDEでのコンソールへのデバッグ出力(Macでは不完全)

推奨はUART使うらしいですが、簡単に実行するにはデバッグコンソールに出したいよね、ということでやってみたけど限定的にしか使えないから補助的な使い方になりそうだ

<環境>

・M4 MacBook

・CubeIDE 1.19.0

・STM32F401re

 

<手順>

以下にわかりやすく手順が記されていたので実行してみた

STM32CubeIDEでprintf【SWO編】

SWV(Serial Wire Viewer)を有効にする、SWV経由でデバッグコンソール(SWV ITM Data Console)に出力ということのようらしい

/* USER CODE BEGIN 4 */
int _write(int file, char *ptr, int len)
{
  int DataIdx;
  for(DataIdx=0; DataIdx<len; DataIdx++)
  {
    ITM_SendChar(*ptr++);
  }
  return len;
}
/* USER CODE END 4 */

int _write()関数の実装が必要、実は元の実装がweak指定でそのオーバーライド関数になってます

ITM Stimulus ポートにチェック、このポートを使うらしい

デバッグ用のprintf文は二箇所に入れてみた

  /* USER CODE BEGIN 1 */
	printf("---------------0078\r\n");
  /* USER CODE END 1 */

  /* USER CODE BEGIN WHILE */
	while (1) {
		if (adc_conv_complete_flag == 1) {
			adc_conv_complete_flag = 0;
			printf("---------------0111\r\n");
			// delay for 500 Milliseconds
			//HAL_Delay(500);
		}
	}
    /* USER CODE END WHILE */

埋め込みは、このプロジェクトの中のソースに、

https://isehara-3lv.sakura.ne.jp/blog/wp-admin/post.php?post=5058&action=edit

なぜおまじないのような”———“が入っているか、それはApple silicon(Intelでも同じかも)のMacではST-LINKの動作がイマイチ不安定で、

終わりの方の文字しか出力されない現象、ループ中では全部出力されてるけどもね、デバッガで変数の値を見れる環境ならば、最低限ここは通ったよという行数情報だけでも良さそうだからこうやってみた、但しwhile()中では出力されない時とまとめて二行出力される時とかあって不安定な雰囲気

FreeRTOSの場合には、タスク優先度考慮必要でちょっと違うみたいだね

 

admin

ADCをDMA転送で実行してみる

今回のテーマはADCを扱うのと、データ転送はDMAを使うこと

tutorialは、

https://embeddedthere.com/stm32-adc-tutorial-using-dma-with-hal-code-example/

但しいくつか変更を入れていて、

① ADCは一チャンネルだけにする(入力は3.3VとGNDで見てみる)

② DMA転送領域は拡大する

③ UARTは使わずに転送されたデータはデバッガでみることにする

 

<環境>

・M4 MacBook Pro(Tahoe)

・CubeIDE:1.19.0

・STM32F401re

 

<結果>

ADCの入力に3.3V入れた見た図

ADCの入力をGND接続時の図

この範囲で守る限りはADCの有効ビットはラズピコよりもあるように見える

 

<最終的なコードmain.c>

/* USER CODE BEGIN Header */
/**
 ******************************************************************************
 * @file           : main.c
 * @brief          : Main program body
 ******************************************************************************
 * @attention
 *
 * Copyright (c) 2025 STMicroelectronics.
 * All rights reserved.
 *
 * This software is licensed under terms that can be found in the LICENSE file
 * in the root directory of this software component.
 * If no LICENSE file comes with this software, it is provided AS-IS.
 *
 ******************************************************************************
 */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */
#define DMA_COUNTS 128
volatile uint16_t adc_dma_result[DMA_COUNTS];
// int adc_channel_count = sizeof(adc_dma_result) / sizeof(adc_dma_result[0]);
uint8_t adc_conv_complete_flag = 0;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_ADC1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_USART2_UART_Init();
  MX_ADC1_Init();
  /* USER CODE BEGIN 2 */
	HAL_ADC_Start_DMA(&hadc1, (uint32_t*) adc_dma_result, DMA_COUNTS);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	while (1) {
		if (adc_conv_complete_flag == 1) {
			adc_conv_complete_flag = 0;
			// delay for 500 Milliseconds
			HAL_Delay(500);
		}
	}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 16;
  RCC_OscInitStruct.PLL.PLLN = 336;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV4;
  RCC_OscInitStruct.PLL.PLLQ = 7;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief ADC1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_ADC1_Init(void)
{

  /* USER CODE BEGIN ADC1_Init 0 */

  /* USER CODE END ADC1_Init 0 */

  ADC_ChannelConfTypeDef sConfig = {0};

  /* USER CODE BEGIN ADC1_Init 1 */

  /* USER CODE END ADC1_Init 1 */

  /** Configure the global features of the ADC (Clock, Resolution, Data Alignment and number of conversion)
  */
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 1;
  hadc1.Init.DMAContinuousRequests = ENABLE;
  hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
  */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN ADC1_Init 2 */

  /* USER CODE END ADC1_Init 2 */

}

/**
  * @brief USART2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_USART2_UART_Init(void)
{

  /* USER CODE BEGIN USART2_Init 0 */

  /* USER CODE END USART2_Init 0 */

  /* USER CODE BEGIN USART2_Init 1 */

  /* USER CODE END USART2_Init 1 */
  huart2.Instance = USART2;
  huart2.Init.BaudRate = 115200;
  huart2.Init.WordLength = UART_WORDLENGTH_8B;
  huart2.Init.StopBits = UART_STOPBITS_1;
  huart2.Init.Parity = UART_PARITY_NONE;
  huart2.Init.Mode = UART_MODE_TX_RX;
  huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart2.Init.OverSampling = UART_OVERSAMPLING_16;
  if (HAL_UART_Init(&huart2) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN USART2_Init 2 */

  /* USER CODE END USART2_Init 2 */

}

/**
  * Enable DMA controller clock
  */
static void MX_DMA_Init(void)
{

  /* DMA controller clock enable */
  __HAL_RCC_DMA2_CLK_ENABLE();

  /* DMA interrupt init */
  /* DMA2_Stream0_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
  HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  /* USER CODE BEGIN MX_GPIO_Init_1 */

  /* USER CODE END MX_GPIO_Init_1 */

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOH_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : B1_Pin */
  GPIO_InitStruct.Pin = B1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  HAL_GPIO_Init(B1_GPIO_Port, &GPIO_InitStruct);

  /*Configure GPIO pin : LD2_Pin */
  GPIO_InitStruct.Pin = LD2_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(LD2_GPIO_Port, &GPIO_InitStruct);

  /* USER CODE BEGIN MX_GPIO_Init_2 */

  /* USER CODE END MX_GPIO_Init_2 */
}

/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) {
	adc_conv_complete_flag = 1;
    //HAL_ADC_Stop_DMA(hadc);
    //HAL_ADC_Start_DMA(hadc, (uint32_t*)adc_dma_result, DMA_COUNTS);
}
/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
	/* User can add his own implementation to report the HAL error return state */
	__disable_irq();
	while (1) {
	}
  /* USER CODE END Error_Handler_Debug */
}
#ifdef USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

これあくまで動作確認用で、本来的にはADCのサンプリング周期は別途のタイマーで決めるべきだから、実用的にはこれではダメ

 

admin

CubeIDEでのデバッガ(変数を対象にするとき)

CubeIDEにはST-LINKを使ったデバッグ機能がありますが、関連のソフトも自動でインストされる、しかしIDEごとにUIは微妙に異なるのでCubeIDEでの事例です

FreeRTOSを動かしてみる

やり方はすでに作成済みのRTOSのサンプルコードに追加変更して実行

valueとvalue2というint型の変数を追加、ブレークポイントを変数の更新行においてデバッガ起動

ユーザコード指定以外に記述すると消されるので、記載位置だけは注意が必要でしょう

/* USER CODE BEGIN PV */
volatile int value = 0;
volatile int value2 = 0;
/* USER CODE END PV */


void task_1_function(void *argument)
{
  /* USER CODE BEGIN 5 */
  /* Infinite loop */
  for(;;)
  {
	HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_4);
    osDelay(100);
    value++;
  }
  /* USER CODE END 5 */
}

同様にtask_2中ではvalue2をカウントアップする

デバッグ対象変数の追加方法はいくつかありますが、ここでは、

Show View -> Expressionsで窓開いて、

Add new expressionsで変数を追加、ラズピコのデバッガでのやり方と大差ない

それぞれのタスクの実行回数比率は1:2だからこんな感じで見えます

 

admin

FreeRTOSを動かしてみる

STM32CubeIDEのRTOSはFreeRTOSと系列は共通でもCMSISでラップされているので、APIは違いがあるようですが、RTOS使うのもCube32MXで設定できるので使う上ではそれほどの違いはない

https://embeddedthere.com/getting-started-with-freertos-in-stm32-example-code-included/

が分かりやすいのでこれを参考にした、ただしRTOSといってもタスクを起動とかはしてなくて最初に二つのタスクを起動したら永久に動き続けるだけ

<動作環境>

・M4 MacBook:CubeIDEの1系ならちゃんと動くから

・CubeIDE:1.19.0

・STM32F401re

<手順>

解説中では言及されてませんが、ビルドする時に設定が必要でした、

ビルドするとポップアップで確認メッセージが出てくるので、USE_NEWLIB_REENTRANT(thread safeにするためらしい、その分多少のメモリ増加はするけど、シングルタスク以外はenableにすべきなんだろう)をEnabledにしました

また目で見て簡単にわかるように、PB5側はPA5(つまりオンボードLED)にしています、ソースコードは以下に修正しています

待ちでosDelayを使う理由は、他のタスクへの実行権限以上をできるようにするため、HAL_Delayは単なるアイドリング状態、つまりMCUは動き続ける、だから無駄にリソース消費する

オシロでPB4とPA5の波形を見ると、ほぼ設定した時間でトグルされているのが分かります、普通はタスクが独立してフリーに動作することはほぼないので、次はタスクを待ち状態から起動させてみます

 

admin

STM32Nucleoのデフォルト発信器はRC発振なのか

STM32でPWM発信をさせた時に、計算上は1KHzでも実際の発振周波数は1015Hzぐらいでジッターも1μsぐらいはある

https://moons.link/post-632/

なぜ水晶発振なのにそんな振れるのかと思ったけど、実は内部ではRC発信器が動いているということ

無論水晶振動子を追加して、そちらを選択もできるようになってます、発信の立ち上がり時間はかかりますが、アプリケーションによってはこの程度の精度でも問題なくて値段が重要という時には水晶使わないケースもあるということだろう

Morphoコネクタに大概の信号は出力されているので、そこからプローブ可能

 

admin

 

 

 

 

Sesameでリモコンがスマホから見えない

セサミの不具合(その1)

ファームのアップデートかなり頻繁にあり、内容までは記載されてないようですが、先進機能取り込みの影響なのか結構Buggyでもあります、感覚的には二ヶ月に一回ぐらいは何らかの対処必要な感じ

Sesameのファームアップデート後にクローズセンサーと連携しなくなったので触ってる間にリモコンがスマホから見えなくなった

サポートの回答はスマホとのリンクが切れてる?とか言ってログインしてリセットしろとか言ってたけど、余計状況が悪化しそうなので、とりあえず使える間は使おうと思う

今までゲストでデバイス登録してたけど、スマホ移行すると登録情報消えるからログインしてクラウド保存が正統らしい、今はゲスト状態からログインしてスマホはsesameデバイス見えない状態だけど、スマホとsesameデバイスとのBLE接続情報は残ってるぽい(スマホのPASMOオープン使えるから)無論sesameデバイス間でも連携ができている状況でしょう、そのうち長時間動作でメモリリークなどで問題も起きるだろうけど、その時の対処は起きてから考える

とりあえずデフォルトのYKKのスマートキーはある訳だから、多少不便(オープンセンサーと生体認証他が使えない)でもそちらの機能使えばいいし、外出の時にsesameだけに頼るのは危険だから必ずYKKの物理キーも持って出るようにしている、スマートキーの実運用では電子的な手段に全部を頼るのは危険だから

 

admin

CubeMXで周辺デバイスの自動初期化

CubeIDEはCubeMXと統合されてますが、元々は別れてたらしい、CubeIDEの特徴とも言える機能で周辺デバイスの設定だけで.iocファイルを作成して、buildで対応するコードを生成してコード側にはロジックの記述だけという役割分担のようです

<環境>

・Intel MacBook Ventura

・CubeIDE 1.10.0

参考は、

https://moons.link/post-50/

からTimerの初期設定と、Timerを使ったLチカを実行してみました、そのまんまですが、全体の流れと手順は、

Categories(TIM1) -> ModeのClock SourceをInternal Clock -> Parameter Setting(タイマーの動作設定) -> NVIC Setting(TIM1 update・・をEnableにチェック) -> main.cにTIM1の動作起動コードの追加 -> Core > Startup中のstartup_stm32f401retx.s(割り込みベクタ記述のアセンブラコード)中の割り込みベクターに対応する割り込み処理を記述(LED表示のトグル処理、stm32f4xx_it.c中に記述)

このLチカはタイマー割り込み使わずに普通に時間待ちしてもできる訳だけど、敢えて割り込み使った処理にしているだけです

※NVIC(Nested Vectored Interrupt Controller)、普通に割り込み優先順ごとに処理するハードウェア機能

以上完了後にBuildすれば実行可能ということ

参考ページの記述にはClock SourceをInternal Clockにすれば設定画面が開くとありましたが、リロード(?)しないと見えてこなかった

CubeMXの初期設定で作成された結果は、main.cの中にちゃんと見えて(184行目以降)きてますね

このディレクトリ構成はタイマー機能をMXで指定後に自動作成されるファイルを含んでいます、stm32f4xx — .cが該当します、stm32f4xx_hal_msp.c(mspはMCU Support Package)は周辺デバイス追加してもその中で複数の該当周辺デバイスの初期化コードを呼び出すので一個のままで、stm32f4x_it.cは周辺デバイスごとに追加されていくと思う

MXの設定で最初Prescallerを39999(10倍の値)にしてたので、1秒間隔じゃなく10秒間隔でブリンクしてましたが、Buildエラーさえでなけりゃ指定したままちゃんと動くということ

一度ST-LINKを経由した書き込まれたコードはFlash上への書き込みなので、ラズピコなどと同じく、電源切っても再度電源投入すればそのまま動き出します

動作時の動画、

 

admin