BBD コーラス (5) -- STM32VL Discovery プログラム (2)

1024 段 BBD をエミュレートする C ソース・プログラムを下に示します。
長くなるので、プログラムの説明は後に回し、コンパイル方法だけを説明します。
まず、コンパイルには「Atollic TrueSTUDIO/STM32 Lite version 1.4.0」を使いました。
TrueSTUDIO/STM32 の IDE を立ち上げ、File メニューの Switch Workspace / Other... とたどって、新規ワークスペースを作成します。
次に、File メニューの New / C Project とたどって、STM32_Discovery 用の新規 C プロジェクトを作成します。
そして自動生成される「main.c」を下の内容に置き換えればビルドできます。
TrueSTUDIO/STM32 Lite バージョンでは、各種の設定がデフォルト値から変更できないようになっているので、コンパイルの最適化オプションは「-O0」(オー・ゼロ) 、つまり最適化なしの状態となり、オブジェクト・サイズは 5 K バイト超となります。
サイズは小さいので問題となりませんが、前回の hex ファイルと同様の結果を得るためには、
Project / Properties / C/C++ Build / Settings / C Compiler / Miscellaneous / Other options
のテキストボックスに「-Os」を追加します。
他のコンパイラの環境では試していませんが、STMicro の「STM32F10x Standard Peripherals Libray」を呼び出して周辺モジュールの設定をしているだけなので、「StdPeriph Driver」を使った「LED チカチカ」などのプログラムをコンパイルできる環境なら、同様にしてコンパイルできると思います。
ただし、TrueSTUDIO/STM32 では、アセンブラで記述された C スタートアップ・ルーチン内で SystemInit() 関数を呼び出しているので、下のプログラム中では SystemInit() 関数の呼び出しはコメント・アウトしてあります。
SystemInit() を呼び出さないタイプのスタートアップ・ルーチンを使用している場合には、プログラム中の SystemInit() 関数の呼び出しを有効にする必要があります。
また、TrueSTUDIO/STM32 IDE では、次のシンボルが定義されています。

USE_STM32_DISCOVERY
STM32F10X_MD_VL
USE_STDPERIPH_DRIVER

このうち、「STM32F10X_MD_VL」シンボルで、Medium Density の Value Line、つまり、STM32F100 ファミリに対する設定が選択されるようになっています。
プログラム中で、「USE_STM32_DISCOVERY」シンボルを参照して、DFU ファームウェア用のスペースが存在するかどうかを判定して、NVIC のベクタ・テーブルに設定する値を変えています。

/*****************************************/
/* bbd1024.c -- 1024 stage BBD emulator  */
/*              for STM32VL Discovery    */
/*                                       */
/* Signal Input : PC5/ADC1_IN15(P1-24)   */
/* Signal Output: PA4/DAC1_OUT (P1-19)   */
/* BBD Clock  In: PB9          (P3-25)   */
/*                PA11         (P3-9)    */
/*                                       */
/* 2011/05/29 Created by pcm1723         */
/*****************************************/

#include <stddef.h>
#include "stm32f10x.h"

#define ADC_TRIG_PORT     GPIOA
#define ADC_TRIG_PORT_SRC GPIO_PortSourceGPIOA
#define DAC_TRIG_PORT     GPIOB
#define DAC_TRIG_PORT_SRC GPIO_PortSourceGPIOB

#define SIG_IN_PORT   GPIOC
#define SIG_IN_BIT    GPIO_Pin_5
#define SIG_IN_CH     ADC_Channel_15
#define SIG_SAMP_TIME ADC_SampleTime_28Cycles5

#define GREEN_LED(on_off) GPIO_WriteBit(GPIOC, GPIO_Pin_9, (on_off))
#define BLUE_LED(on_off)  GPIO_WriteBit(GPIOC, GPIO_Pin_8, (on_off))

#define DELAY_MEM_SIZE 1024

int16_t delay_mem[DELAY_MEM_SIZE];

void NVIC_configuration( void )
{
#if defined(USE_STM32_DISCOVERY)
// no DFU firmware for STM32VL Discovery
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0000);
#else
// room for DFU firmware
  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x3000);
#endif
} // void NVIC_configuration()

void GPIO_configuration( void )
{
  GPIO_InitTypeDef GPIO_InitStruct;
// enable GPIO A/B/C clocking
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
// enable clocking for AFIO
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE);
// initialize PC8 (P3-4) for Blue LED
  GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_8;
  GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_Init(GPIOC, &GPIO_InitStruct);
// initialize PC9 (P3-5) for Green LED
  GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_9;
  GPIO_Init(GPIOC, &GPIO_InitStruct);
// initialize PA11 (P3-9) for EXTI_11 (ADC trigger)
  GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_11;
  GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_IPD;
  GPIO_Init(ADC_TRIG_PORT, &GPIO_InitStruct);
// initialize PA9 (P3-7) for EXTI_9 (DAC trigger)
  GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_9;
  GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_IPD;
  GPIO_Init(DAC_TRIG_PORT, &GPIO_InitStruct);
} // void GPIO_configuration()

void DAC_configuration( void )
{
  GPIO_InitTypeDef GPIO_InitStruct;
  DAC_InitTypeDef  DAC_InitStruct;
// Enable DAC Clock
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
// Configure DAC1_OUT/PA4 (P1-19) as analog input
  GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_4;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(GPIOA, &GPIO_InitStruct);
// DAC1 for signal output
  DAC_StructInit(&DAC_InitStruct);
  DAC_InitStruct.DAC_Trigger = DAC_Trigger_Ext_IT9;
  DAC_Init  (DAC_Channel_1, &DAC_InitStruct);
  DAC_DMACmd(DAC_Channel_1, ENABLE); // start DMA
  DAC_Cmd   (DAC_Channel_1, ENABLE); // enable DAC
} // void DAC_configuratio()

void DMA_configuration( void )
{
  DMA_InitTypeDef DMA_InitStruct;
// enable clock for DMA1 module
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
  DMA_StructInit(&DMA_InitStruct);
// DMA from delay_mem[] to DAC1 right-justified data reg
  DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12R1);
  DMA_InitStruct.DMA_MemoryBaseAddr     = (uint32_t)&(delay_mem[0]);
  DMA_InitStruct.DMA_DIR                = DMA_DIR_PeripheralDST;
  DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
  DMA_InitStruct.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;
  DMA_InitStruct.DMA_MemoryInc          = DMA_MemoryInc_Enable;
  DMA_InitStruct.DMA_Mode               = DMA_Mode_Circular;
  DMA_InitStruct.DMA_BufferSize         = DELAY_MEM_SIZE;
  DMA_Init(DMA1_Channel3, &DMA_InitStruct);
  DMA_Cmd (DMA1_Channel3, ENABLE); // start DMA1 Ch3 for DAC1
// DMA from right-justified ADC1 to delay_mem[]
  DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&(ADC1->DR);
  DMA_InitStruct.DMA_MemoryBaseAddr     = (uint32_t)&(delay_mem[0]);
  DMA_InitStruct.DMA_DIR                = DMA_DIR_PeripheralSRC;
  DMA_Init(DMA1_Channel1, &DMA_InitStruct);
  DMA_Cmd (DMA1_Channel1, ENABLE); // start DMA1 Ch1 for ADC1
} // void DMA_configuration()

void EXTI_configuration( void )
{
  EXTI_InitTypeDef EXTI_InitStruct;
// assign PB9 (P3-25) as EXTI9 for DAC1 trigger
  GPIO_EXTILineConfig(DAC_TRIG_PORT_SRC, GPIO_PinSource9);
  EXTI_InitStruct.EXTI_Line    = EXTI_Line9;
  EXTI_InitStruct.EXTI_LineCmd = ENABLE;
  EXTI_InitStruct.EXTI_Mode    = EXTI_Mode_Event ;
  EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
  EXTI_Init(&EXTI_InitStruct);
// assign PA11 (P3-9) as EXTI11 for ADC1 trigger
  GPIO_EXTILineConfig(ADC_TRIG_PORT_SRC, GPIO_PinSource11);
  EXTI_InitStruct.EXTI_Line    = EXTI_Line11;
  EXTI_Init(&EXTI_InitStruct);
} // void EXTI_config()

void ADC_configuration( void )
{
  GPIO_InitTypeDef GPIO_InitStruct;
  ADC_InitTypeDef  ADC_InitStruct;
// ADC clock prescaler
  RCC_ADCCLKConfig(RCC_PCLK2_Div2);// 24 MHz/2 = 12 MHz
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
  ADC_Cmd(ADC1, ENABLE); // power ON
// start calibration
  ADC_ResetCalibration(ADC1);
  while(SET == ADC_GetResetCalibrationStatus(ADC1)) {}
  ADC_StartCalibration(ADC1);
  while(SET == ADC_GetCalibrationStatus(ADC1)) {}
// Configure ADC1_IN15/PC5 (P1-24) as analog input
  GPIO_InitStruct.GPIO_Pin  = SIG_IN_BIT;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AIN;
  GPIO_Init(SIG_IN_PORT, &GPIO_InitStruct);
  ADC_StructInit(&ADC_InitStruct);
// regular group ADC for signal input
  ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO;
  ADC_InitStruct.ADC_ScanConvMode     = ENABLE;
  ADC_Init(ADC1, &ADC_InitStruct);
// T_conv = (28.5 + 12.5) / 12 [MHz] = 3.42 [us]
  ADC_RegularChannelConfig(ADC1, SIG_IN_CH, 1, SIG_SAMP_TIME);
  ADC_ExternalTrigConvCmd (ADC1, ENABLE);
  ADC_DMACmd(ADC1, ENABLE);
} // void ADC_configuration()

void hardware_config( void )
{
//  SystemInit();
  NVIC_configuration();
  GPIO_configuration();
  DAC_configuration();
  DMA_configuration();
  ADC_configuration();
  EXTI_configuration();
} // void hardware_config()

int main(void)
{
  hardware_config();
  GREEN_LED(1);
  BLUE_LED(1);
  for (;;) {
  } // for (;;)
} // int main()