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()