diff --git a/bsp/stm32_radio/board.c b/bsp/stm32_radio/board.c index 94311b45ce..5f50ac70ff 100644 --- a/bsp/stm32_radio/board.c +++ b/bsp/stm32_radio/board.c @@ -18,6 +18,8 @@ #include "stm32f10x.h" #include "board.h" +struct rt_semaphore spi1_lock; + /** * @addtogroup STM32 */ @@ -87,7 +89,7 @@ static void all_device_reset(void) | RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG,ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; /* SDIO POWER */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; @@ -279,6 +281,11 @@ void rt_hw_board_init() /* Enable SPI_MASTER */ SPI_Cmd(SPI1, ENABLE); SPI_CalculateCRC(SPI1, DISABLE); + + if (rt_sem_init(&spi1_lock, "spi1lock", 1, RT_IPC_FLAG_FIFO) != RT_EOK) + { + rt_kprintf("init spi1 lock semaphore failed\n"); + } } }/* rt_hw_board_init */ diff --git a/bsp/stm32_radio/board.h b/bsp/stm32_radio/board.h index 5adb58e2e2..bc40a0486d 100644 --- a/bsp/stm32_radio/board.h +++ b/bsp/stm32_radio/board.h @@ -69,6 +69,8 @@ void rt_hw_board_init(void); void rt_hw_usart_init(void); void rt_hw_sdcard_init(void); +extern struct rt_semaphore spi1_lock; + #endif // <<< Use Configuration Wizard in Context Menu >>> diff --git a/bsp/stm32_radio/codec.c b/bsp/stm32_radio/codec.c index bda54d3fb0..74cc419842 100644 --- a/bsp/stm32_radio/codec.c +++ b/bsp/stm32_radio/codec.c @@ -81,6 +81,10 @@ struct codec_device codec; static uint16_t r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV8; +#if !CODEC_MASTER_MODE +static int codec_sr_new = 0; +#endif + static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; @@ -97,49 +101,49 @@ static void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; - /* Disable the JTAG interface and enable the SWJ interface */ - GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); + /* Disable the JTAG interface and enable the SWJ interface */ + GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); - /* PC5 CODEC CS */ - GPIO_InitStructure.GPIO_Pin = CODEC_CSB_PIN; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; - GPIO_Init(CODEC_CSB_PORT, &GPIO_InitStructure); + /* PC5 CODEC CS */ + GPIO_InitStructure.GPIO_Pin = CODEC_CSB_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_Init(CODEC_CSB_PORT, &GPIO_InitStructure); - // WS - GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; + // WS + GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; #if CODEC_MASTER_MODE - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; #else - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; #endif - GPIO_Init(CODEC_I2S_WS_PORT, &GPIO_InitStructure); + GPIO_Init(CODEC_I2S_WS_PORT, &GPIO_InitStructure); - // CK - GPIO_InitStructure.GPIO_Pin = CODEC_I2S_CK_PIN; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; + // CK + GPIO_InitStructure.GPIO_Pin = CODEC_I2S_CK_PIN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; #if CODEC_MASTER_MODE - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; #else - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; #endif - GPIO_Init(CODEC_I2S_CK_PORT, &GPIO_InitStructure); + GPIO_Init(CODEC_I2S_CK_PORT, &GPIO_InitStructure); - // SD - GPIO_InitStructure.GPIO_Pin = CODEC_I2S_SD_PIN; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; - GPIO_Init(CODEC_I2S_SD_PORT, &GPIO_InitStructure); + // SD + GPIO_InitStructure.GPIO_Pin = CODEC_I2S_SD_PIN; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_Init(CODEC_I2S_SD_PORT, &GPIO_InitStructure); #ifdef CODEC_USE_MCO - /* MCO configure */ - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_Init(GPIOA,&GPIO_InitStructure); + /* MCO configure */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA,&GPIO_InitStructure); - RCC_MCOConfig(RCC_MCO_HSE); + RCC_MCOConfig(RCC_MCO_HSE); #endif } @@ -147,132 +151,136 @@ static void DMA_Configuration(rt_uint32_t addr, rt_size_t size) { DMA_InitTypeDef DMA_InitStructure; - /* DMA Channel configuration ----------------------------------------------*/ - DMA_Cmd(CODEC_I2S_DMA, DISABLE); - DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(CODEC_I2S_PORT->DR)); - DMA_InitStructure.DMA_MemoryBaseAddr = (u32) addr; - DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; - DMA_InitStructure.DMA_BufferSize = size; - DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; - DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; - DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; - DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; - DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; - DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; - DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; - DMA_Init(CODEC_I2S_DMA, &DMA_InitStructure); + /* DMA Channel configuration ----------------------------------------------*/ + DMA_Cmd(CODEC_I2S_DMA, DISABLE); + DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(CODEC_I2S_PORT->DR)); + DMA_InitStructure.DMA_MemoryBaseAddr = (u32) addr; + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; + DMA_InitStructure.DMA_BufferSize = size; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; + DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; + DMA_Init(CODEC_I2S_DMA, &DMA_InitStructure); - /* Enable SPI DMA Tx request */ - SPI_I2S_DMACmd(CODEC_I2S_PORT, SPI_I2S_DMAReq_Tx, ENABLE); + /* Enable SPI DMA Tx request */ + SPI_I2S_DMACmd(CODEC_I2S_PORT, SPI_I2S_DMAReq_Tx, ENABLE); - DMA_ITConfig(CODEC_I2S_DMA, DMA_IT_TC, ENABLE); - DMA_Cmd(CODEC_I2S_DMA, ENABLE); + DMA_ITConfig(CODEC_I2S_DMA, DMA_IT_TC, ENABLE); + DMA_Cmd(CODEC_I2S_DMA, ENABLE); } static void I2S_Configuration(uint32_t I2S_AudioFreq) { - I2S_InitTypeDef I2S_InitStructure; + I2S_InitTypeDef I2S_InitStructure; - /* I2S peripheral configuration */ - I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; - I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; - I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; - I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq; - I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; + /* I2S peripheral configuration */ + I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips; + I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b; + I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable; + I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq; + I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low; - /* I2S2 configuration */ + /* I2S2 configuration */ #if CODEC_MASTER_MODE - I2S_InitStructure.I2S_Mode = I2S_Mode_SlaveTx; + I2S_InitStructure.I2S_Mode = I2S_Mode_SlaveTx; #else - I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; + I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx; #endif - I2S_Init(CODEC_I2S_PORT, &I2S_InitStructure); + I2S_Init(CODEC_I2S_PORT, &I2S_InitStructure); } uint8_t SPI_WriteByte(unsigned char data) { - //Wait until the transmit buffer is empty - while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); - // Send the byte - SPI_I2S_SendData(SPI1, data); + //Wait until the transmit buffer is empty + while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET); + // Send the byte + SPI_I2S_SendData(SPI1, data); - //Wait until a data is received - while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); - // Get the received data - data = SPI_I2S_ReceiveData(SPI1); + //Wait until a data is received + while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); + // Get the received data + data = SPI_I2S_ReceiveData(SPI1); - // Return the shifted data - return data; + // Return the shifted data + return data; } static void codec_send(rt_uint16_t s_data) { - codec_reset_csb(); - SPI_WriteByte((s_data >> 8) & 0xFF); - SPI_WriteByte(s_data & 0xFF); - codec_set_csb(); + rt_sem_take(&spi1_lock, RT_WAITING_FOREVER); + + codec_reset_csb(); + SPI_WriteByte((s_data >> 8) & 0xFF); + SPI_WriteByte(s_data & 0xFF); + codec_set_csb(); + + rt_sem_release(&spi1_lock); } static rt_err_t codec_init(rt_device_t dev) { - codec_send(REG_SOFTWARE_RESET); + codec_send(REG_SOFTWARE_RESET); - // 1.5x boost power up sequence. - // Mute all outputs. - codec_send(REG_LOUT1_VOL | LOUT1MUTE); - codec_send(REG_ROUT1_VOL | ROUT1MUTE); - codec_send(REG_LOUT2_VOL | LOUT2MUTE); - codec_send(REG_ROUT2_VOL | ROUT2MUTE); - // Enable unused output chosen from L/ROUT2, OUT3 or OUT4. - codec_send(REG_POWER_MANAGEMENT3 | OUT4EN); - // Set BUFDCOPEN=1 and BUFIOEN=1 in register R1 - codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN); - // Set SPKBOOST=1 in register R49. - codec_send(REG_OUTPUT | SPKBOOST); - // Set VMIDSEL[1:0] to required value in register R1. - codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K); - // Set L/RMIXEN=1 and DACENL/R=1 in register R3. - codec_send(REG_POWER_MANAGEMENT3 | LMIXEN | RMIXEN | DACENL | DACENR); - // Set BIASEN=1 in register R1. - codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K | BIASEN); - // Set L/ROUT2EN=1 in register R3. - codec_send(REG_POWER_MANAGEMENT3 | LMIXEN | RMIXEN | DACENL | DACENR | LOUT2EN | ROUT2EN); - // Enable other mixers as required. - // Enable other outputs as required. - codec_send(REG_POWER_MANAGEMENT2 | LOUT1EN | ROUT1EN | BOOSTENL | BOOSTENR | INPPGAENL | INPPGAENR); + // 1.5x boost power up sequence. + // Mute all outputs. + codec_send(REG_LOUT1_VOL | LOUT1MUTE); + codec_send(REG_ROUT1_VOL | ROUT1MUTE); + codec_send(REG_LOUT2_VOL | LOUT2MUTE); + codec_send(REG_ROUT2_VOL | ROUT2MUTE); + // Enable unused output chosen from L/ROUT2, OUT3 or OUT4. + codec_send(REG_POWER_MANAGEMENT3 | OUT4EN); + // Set BUFDCOPEN=1 and BUFIOEN=1 in register R1 + codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN); + // Set SPKBOOST=1 in register R49. + codec_send(REG_OUTPUT | SPKBOOST); + // Set VMIDSEL[1:0] to required value in register R1. + codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K); + // Set L/RMIXEN=1 and DACENL/R=1 in register R3. + codec_send(REG_POWER_MANAGEMENT3 | LMIXEN | RMIXEN | DACENL | DACENR); + // Set BIASEN=1 in register R1. + codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K | BIASEN); + // Set L/ROUT2EN=1 in register R3. + codec_send(REG_POWER_MANAGEMENT3 | LMIXEN | RMIXEN | DACENL | DACENR | LOUT2EN | ROUT2EN); + // Enable other mixers as required. + // Enable other outputs as required. + codec_send(REG_POWER_MANAGEMENT2 | LOUT1EN | ROUT1EN | BOOSTENL | BOOSTENR | INPPGAENL | INPPGAENR); - // Digital inferface setup. - codec_send(REG_AUDIO_INTERFACE | BCP_NORMAL | LRP_NORMAL | WL_16BITS | FMT_I2S); + // Digital inferface setup. + codec_send(REG_AUDIO_INTERFACE | BCP_NORMAL | LRP_NORMAL | WL_16BITS | FMT_I2S); - // PLL setup. - // fs = 44.1KHz * 256fs = 11.2896MHz - // F_PLL = 11.2896MHz * 4 * 2 = 90.3168MHz - // R = 90.3168MHz / 12.288MHz = 7.35 - // PLL_N = 7 - // PLL_K = 0x59999A (0x5A5A5A for STM32's 44.117KHz fs generated from 72MHz clock) - codec_send(REG_PLL_N | 7); + // PLL setup. + // fs = 44.1KHz * 256fs = 11.2896MHz + // F_PLL = 11.2896MHz * 4 * 2 = 90.3168MHz + // R = 90.3168MHz / 12.288MHz = 7.35 + // PLL_N = 7 + // PLL_K = 0x59999A (0x5A5A5A for STM32's 44.117KHz fs generated from 72MHz clock) + codec_send(REG_PLL_N | 7); #if CODEC_MASTER_MODE - codec_send(REG_PLL_K1 | 0x16); - codec_send(REG_PLL_K2 | 0xCC); - codec_send(REG_PLL_K3 | 0x19A); + codec_send(REG_PLL_K1 | 0x16); + codec_send(REG_PLL_K2 | 0xCC); + codec_send(REG_PLL_K3 | 0x19A); #else - codec_send(REG_PLL_K1 | 0x16); - codec_send(REG_PLL_K2 | 0x12D); - codec_send(REG_PLL_K3 | 0x5A); + codec_send(REG_PLL_K1 | 0x16); + codec_send(REG_PLL_K2 | 0x12D); + codec_send(REG_PLL_K3 | 0x5A); #endif - codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K | BIASEN | PLLEN); - codec_send(r06); + codec_send(REG_POWER_MANAGEMENT1 | BUFDCOPEN | BUFIOEN | VMIDSEL_75K | BIASEN | PLLEN); + codec_send(r06); - // Enable DAC 128x oversampling. - codec_send(REG_DAC | DACOSR128); + // Enable DAC 128x oversampling. + codec_send(REG_DAC | DACOSR128); - // Set LOUT2/ROUT2 in BTL operation. - codec_send(REG_BEEP | INVROUT2); + // Set LOUT2/ROUT2 in BTL operation. + codec_send(REG_BEEP | INVROUT2); - // Set output volume. - vol(25); + // Set output volume. + vol(25); - return RT_EOK; + return RT_EOK; } // Exported functions @@ -280,136 +288,136 @@ static rt_err_t codec_init(rt_device_t dev) void vol(uint16_t v) { - v = (v & VOL_MASK) << VOL_POS; - codec_send(REG_LOUT1_VOL | v); - codec_send(REG_ROUT1_VOL | HPVU | v); - codec_send(REG_LOUT2_VOL | v); - codec_send(REG_ROUT2_VOL | SPKVU | v); + v = (v & VOL_MASK) << VOL_POS; + codec_send(REG_LOUT1_VOL | v); + codec_send(REG_ROUT1_VOL | HPVU | v); + codec_send(REG_LOUT2_VOL | v); + codec_send(REG_ROUT2_VOL | SPKVU | v); } void eq(codec_eq_args_t args) { - switch (args->channel) - { - case 1: - codec_send(REG_EQ1 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ3DMODE_DAC : EQ3DMODE_ADC)); - break; + switch (args->channel) + { + case 1: + codec_send(REG_EQ1 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ3DMODE_DAC : EQ3DMODE_ADC)); + break; - case 2: - codec_send(REG_EQ2 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ2BW_WIDE : EQ2BW_NARROW)); - break; + case 2: + codec_send(REG_EQ2 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ2BW_WIDE : EQ2BW_NARROW)); + break; - case 3: - codec_send(REG_EQ3 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ3BW_WIDE : EQ3BW_NARROW)); - break; + case 3: + codec_send(REG_EQ3 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ3BW_WIDE : EQ3BW_NARROW)); + break; - case 4: - codec_send(REG_EQ4 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ4BW_WIDE : EQ4BW_NARROW)); - break; + case 4: + codec_send(REG_EQ4 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS) | (args->mode_bandwidth ? EQ4BW_WIDE : EQ4BW_NARROW)); + break; - case 5: - codec_send(REG_EQ5 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS)); - break; - } + case 5: + codec_send(REG_EQ5 | ((args->frequency & EQC_MASK) << EQC_POS) | ((args->gain & EQG_MASK) << EQG_POS)); + break; + } } // TODO eq1() ~ eq5() are just for testing. To be removed. void eq1(uint8_t freq, uint8_t gain, uint8_t mode) { - codec_send(REG_EQ1 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (mode ? EQ3DMODE_DAC : EQ3DMODE_ADC)); + codec_send(REG_EQ1 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (mode ? EQ3DMODE_DAC : EQ3DMODE_ADC)); } void eq2(uint8_t freq, uint8_t gain, uint8_t bw) { - codec_send(REG_EQ2 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ2BW_WIDE : EQ2BW_NARROW)); + codec_send(REG_EQ2 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ2BW_WIDE : EQ2BW_NARROW)); } void eq3(uint8_t freq, uint8_t gain, uint8_t bw) { - codec_send(REG_EQ3 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ3BW_WIDE : EQ3BW_NARROW)); + codec_send(REG_EQ3 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ3BW_WIDE : EQ3BW_NARROW)); } void eq4(uint8_t freq, uint8_t gain, uint8_t bw) { - codec_send(REG_EQ4 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ4BW_WIDE : EQ4BW_NARROW)); + codec_send(REG_EQ4 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS) | (bw ? EQ4BW_WIDE : EQ4BW_NARROW)); } void eq5(uint8_t freq, uint8_t gain) { - codec_send(REG_EQ2 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS)); + codec_send(REG_EQ2 | ((freq & EQC_MASK) << EQC_POS) | ((gain & EQG_MASK) << EQG_POS)); } void eq3d(uint8_t depth) { - codec_send(REG_3D | ((depth & DEPTH3D_MASK) << DEPTH3D_POS)); + codec_send(REG_3D | ((depth & DEPTH3D_MASK) << DEPTH3D_POS)); } rt_err_t sample_rate(int sr) { - uint16_t r07 = REG_ADDITIONAL; + uint16_t r07 = REG_ADDITIONAL; - switch (sr) - { - case 8000: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV6 | BCLK_DIV8 | (r06 & MS); - r07 |= SR_8KHZ; - break; + switch (sr) + { + case 8000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV6 | BCLK_DIV8 | (r06 & MS); + r07 |= SR_8KHZ; + break; - case 11025: - r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV8 | BCLK_DIV8 | (r06 & MS); - r07 |= SR_12KHZ; - break; + case 11025: + r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV8 | BCLK_DIV8 | (r06 & MS); + r07 |= SR_12KHZ; + break; #if CODEC_MASTER_MODE - case 12000: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV4 | BCLK_DIV8 | (r06 & MS); - r07 |= SR_12KHZ; - break; + case 12000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV4 | BCLK_DIV8 | (r06 & MS); + r07 |= SR_12KHZ; + break; #endif - case 16000: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV3 | BCLK_DIV8 | (r06 & MS); - r07 |= SR_16KHZ; - break; + case 16000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV3 | BCLK_DIV8 | (r06 & MS); + r07 |= SR_16KHZ; + break; - case 22050: - r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV4 | BCLK_DIV8 | (r06 & MS); - r07 |= SR_24KHZ; - break; + case 22050: + r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV4 | BCLK_DIV8 | (r06 & MS); + r07 |= SR_24KHZ; + break; #if CODEC_MASTER_MODE - case 24000: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS); - r07 |= SR_24KHZ; - break; + case 24000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS); + r07 |= SR_24KHZ; + break; #endif - case 32000: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1_5 | BCLK_DIV8 | (r06 & MS); - r07 |= SR_32KHZ; - break; + case 32000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1_5 | BCLK_DIV8 | (r06 & MS); + r07 |= SR_32KHZ; + break; - case 44100: - r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS); - r07 |= SR_48KHZ; - break; + case 44100: + r06 = REG_CLOCK_GEN | CLKSEL_PLL | MCLK_DIV2 | BCLK_DIV8 | (r06 & MS); + r07 |= SR_48KHZ; + break; - case 48000: - r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1 | BCLK_DIV8 | (r06 & MS); - r07 |= SR_48KHZ; - break; + case 48000: + r06 = REG_CLOCK_GEN | CLKSEL_MCLK | MCLK_DIV1 | BCLK_DIV8 | (r06 & MS); + r07 |= SR_48KHZ; + break; - default: - return RT_ERROR; - } - codec_send(r06); - codec_send(r07); + default: + return RT_ERROR; + } + codec_send(r06); + codec_send(r07); #if !CODEC_MASTER_MODE - I2S_Configuration((uint32_t) sr); + codec_sr_new = sr; #endif - return RT_EOK; + return RT_EOK; } FINSH_FUNCTION_EXPORT(vol, Set volume); @@ -424,219 +432,226 @@ FINSH_FUNCTION_EXPORT(sample_rate, Set sample rate); static rt_err_t codec_open(rt_device_t dev, rt_uint16_t oflag) { #if !CODEC_MASTER_MODE - /* enable I2S */ - I2S_Cmd(CODEC_I2S_PORT, ENABLE); + /* enable I2S */ + I2S_Cmd(CODEC_I2S_PORT, ENABLE); #endif - return RT_EOK; + return RT_EOK; } static rt_err_t codec_close(rt_device_t dev) { #if CODEC_MASTER_MODE - if (r06 & MS) - { - CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN; - while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0); - while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0); - CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE; + if (r06 & MS) + { + CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN; + while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0); + while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0); + CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE; - r06 &= ~MS; - codec_send(r06); + r06 &= ~MS; + codec_send(r06); - /* remove all data node */ - if (codec.parent.tx_complete != RT_NULL) - { - rt_base_t level = rt_hw_interrupt_disable(); + /* remove all data node */ + if (codec.parent.tx_complete != RT_NULL) + { + rt_base_t level = rt_hw_interrupt_disable(); - do - { - codec.parent.tx_complete(&codec.parent, codec.data_list[codec.read_index].data_ptr); - codec.read_index++; - if (codec.read_index >= DATA_NODE_MAX) - { - codec.read_index = 0; - } - } - while (codec.read_index != codec.put_index); + do + { + codec.parent.tx_complete(&codec.parent, codec.data_list[codec.read_index].data_ptr); + codec.read_index++; + if (codec.read_index >= DATA_NODE_MAX) + { + codec.read_index = 0; + } + } + while (codec.read_index != codec.put_index); - rt_hw_interrupt_enable(level); - } - } + rt_hw_interrupt_enable(level); + } + } #endif - return RT_EOK; + return RT_EOK; } static rt_err_t codec_control(rt_device_t dev, rt_uint8_t cmd, void *args) { - switch (cmd) - { - case CODEC_CMD_RESET: - codec_init(dev); - break; + switch (cmd) + { + case CODEC_CMD_RESET: + codec_init(dev); + break; - case CODEC_CMD_VOLUME: - vol(*((uint16_t*) args)); - break; + case CODEC_CMD_VOLUME: + vol(*((uint16_t*) args)); + break; - case CODEC_CMD_SAMPLERATE: - dev->close(dev); - sample_rate(*((int*) args)); - dev->open(dev,0); - break; + case CODEC_CMD_SAMPLERATE: + sample_rate(*((int*) args)); + break; - case CODEC_CMD_EQ: - eq((codec_eq_args_t) args); - break; + case CODEC_CMD_EQ: + eq((codec_eq_args_t) args); + break; - case CODEC_CMD_3D: - eq3d(*((uint8_t*) args)); - break; + case CODEC_CMD_3D: + eq3d(*((uint8_t*) args)); + break; - default: - return RT_ERROR; - } - return RT_EOK; + default: + return RT_ERROR; + } + return RT_EOK; } static rt_size_t codec_write(rt_device_t dev, rt_off_t pos, - const void* buffer, rt_size_t size) + const void* buffer, rt_size_t size) { - struct codec_device* device; - struct codec_data_node* node; - rt_uint32_t level; - rt_uint16_t next_index; + struct codec_device* device; + struct codec_data_node* node; + rt_uint32_t level; + rt_uint16_t next_index; - device = (struct codec_device*) dev; - RT_ASSERT(device != RT_NULL); + device = (struct codec_device*) dev; + RT_ASSERT(device != RT_NULL); - next_index = device->put_index + 1; - if (next_index >= DATA_NODE_MAX) - next_index = 0; + next_index = device->put_index + 1; + if (next_index >= DATA_NODE_MAX) + next_index = 0; - /* check data_list full */ - if (next_index == device->read_index) - { - rt_set_errno(-RT_EFULL); - return 0; - } + /* check data_list full */ + if (next_index == device->read_index) + { + rt_set_errno(-RT_EFULL); + return 0; + } - level = rt_hw_interrupt_disable(); - node = &device->data_list[device->put_index]; - device->put_index = next_index; + level = rt_hw_interrupt_disable(); + node = &device->data_list[device->put_index]; + device->put_index = next_index; - /* set node attribute */ - node->data_ptr = (rt_uint16_t*) buffer; - node->data_size = size >> 1; /* size is byte unit, convert to half word unit */ + /* set node attribute */ + node->data_ptr = (rt_uint16_t*) buffer; + node->data_size = size >> 1; /* size is byte unit, convert to half word unit */ - next_index = device->read_index + 1; - if (next_index >= DATA_NODE_MAX) - next_index = 0; + next_index = device->read_index + 1; + if (next_index >= DATA_NODE_MAX) + next_index = 0; - /* check data list whether is empty */ - if (next_index == device->put_index) - { - DMA_Configuration((rt_uint32_t) node->data_ptr, node->data_size); + /* check data list whether is empty */ + if (next_index == device->put_index) + { + DMA_Configuration((rt_uint32_t) node->data_ptr, node->data_size); #if CODEC_MASTER_MODE - if ((r06 & MS) == 0) - { - CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE; - r06 |= MS; - codec_send(r06); - } + if ((r06 & MS) == 0) + { + CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE; + r06 |= MS; + codec_send(r06); + } #endif - } - rt_hw_interrupt_enable(level); + } + rt_hw_interrupt_enable(level); - return size; + return size; } rt_err_t codec_hw_init(void) { - rt_device_t dev; + rt_device_t dev; - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE); - RCC_APB1PeriphClockCmd(CODEC_I2S_RCC_APB1, ENABLE); - RCC_AHBPeriphClockCmd(CODEC_I2S_RCC_AHB, ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE); + RCC_APB1PeriphClockCmd(CODEC_I2S_RCC_APB1, ENABLE); + RCC_AHBPeriphClockCmd(CODEC_I2S_RCC_AHB, ENABLE); - NVIC_Configuration(); - GPIO_Configuration(); - I2S_Configuration(I2S_AudioFreq_44k); + NVIC_Configuration(); + GPIO_Configuration(); + I2S_Configuration(I2S_AudioFreq_44k); - dev = (rt_device_t) &codec; - dev->type = RT_Device_Class_Sound; - dev->rx_indicate = RT_NULL; - dev->tx_complete = RT_NULL; - dev->init = codec_init; - dev->open = codec_open; - dev->close = codec_close; - dev->read = RT_NULL; - dev->write = codec_write; - dev->control = codec_control; - dev->private = RT_NULL; + dev = (rt_device_t) &codec; + dev->type = RT_Device_Class_Sound; + dev->rx_indicate = RT_NULL; + dev->tx_complete = RT_NULL; + dev->init = codec_init; + dev->open = codec_open; + dev->close = codec_close; + dev->read = RT_NULL; + dev->write = codec_write; + dev->control = codec_control; + dev->private = RT_NULL; - /* set read_index and put index to 0 */ - codec.read_index = 0; - codec.put_index = 0; + /* set read_index and put index to 0 */ + codec.read_index = 0; + codec.put_index = 0; - /* unselect */ - codec_set_csb(); + /* unselect */ + codec_set_csb(); - /* register the device */ - return rt_device_register(&codec.parent, "snd", RT_DEVICE_FLAG_WRONLY | RT_DEVICE_FLAG_DMA_TX); + /* register the device */ + return rt_device_register(&codec.parent, "snd", RT_DEVICE_FLAG_WRONLY | RT_DEVICE_FLAG_DMA_TX); } void codec_dma_isr(void) { - /* switch to next buffer */ - rt_uint16_t next_index; - void* data_ptr; + /* switch to next buffer */ + rt_uint16_t next_index; + void* data_ptr; - next_index = codec.read_index + 1; - if (next_index >= DATA_NODE_MAX) - next_index = 0; + next_index = codec.read_index + 1; + if (next_index >= DATA_NODE_MAX) + next_index = 0; - /* save current data pointer */ - data_ptr = codec.data_list[codec.read_index].data_ptr; + /* save current data pointer */ + data_ptr = codec.data_list[codec.read_index].data_ptr; - codec.read_index = next_index; - if (next_index != codec.put_index) - { - /* enable next dma request */ - DMA_Configuration((rt_uint32_t) codec.data_list[codec.read_index].data_ptr, codec.data_list[codec.read_index].data_size); - -#if CODEC_MASTER_MODE - if ((r06 & MS) == 0) - { - CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE; - r06 |= MS; - codec_send(r06); - } -#endif - } - else - { -#if CODEC_MASTER_MODE - if (r06 & MS) - { - CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN; - while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0); - while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0); - CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE; - - r06 &= ~MS; - codec_send(r06); - } +#if !CODEC_MASTER_MODE + if (codec_sr_new) + { + I2S_Configuration(codec_sr_new); + I2S_Cmd(CODEC_I2S_PORT, ENABLE); + codec_sr_new = 0; + } #endif - rt_kprintf("*\n"); - } + codec.read_index = next_index; + if (next_index != codec.put_index) + { + /* enable next dma request */ + DMA_Configuration((rt_uint32_t) codec.data_list[codec.read_index].data_ptr, codec.data_list[codec.read_index].data_size); - /* notify transmitted complete. */ - if (codec.parent.tx_complete != RT_NULL) - { - codec.parent.tx_complete(&codec.parent, data_ptr); - } +#if CODEC_MASTER_MODE + if ((r06 & MS) == 0) + { + CODEC_I2S_PORT->I2SCFGR |= SPI_I2SCFGR_I2SE; + r06 |= MS; + codec_send(r06); + } +#endif + } + else + { +#if CODEC_MASTER_MODE + if (r06 & MS) + { + CODEC_I2S_DMA->CCR &= ~DMA_CCR1_EN; + while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_TXE) == 0); + while ((CODEC_I2S_PORT->SR & SPI_I2S_FLAG_BSY) != 0); + CODEC_I2S_PORT->I2SCFGR &= ~SPI_I2SCFGR_I2SE; + + r06 &= ~MS; + codec_send(r06); + } +#endif + + rt_kprintf("*\n"); + } + + /* notify transmitted complete. */ + if (codec.parent.tx_complete != RT_NULL) + { + codec.parent.tx_complete(&codec.parent, data_ptr); + } } diff --git a/bsp/stm32_radio/spi_flash.c b/bsp/stm32_radio/spi_flash.c index eded43dda4..5f78eb774c 100644 --- a/bsp/stm32_radio/spi_flash.c +++ b/bsp/stm32_radio/spi_flash.c @@ -1,8 +1,22 @@ #include +#include "board.h" #include "spi_flash.h" #include "rtthread.h" -extern unsigned char SPI_WriteByte(unsigned char data); +/* + * WARNING: !!! ENABLING DMA MODE MAY DESTROY YOUR DATA IN THE SPI FLASH !!! + * Don't set SPI_FLASH_USE_DMA to 1 unless you know what you're doing! + * However, readonly access is just fine. :) + */ +#define SPI_FLASH_USE_DMA 0 +#define SECTOR_SIZE 512 + +extern uint8_t SPI_WriteByte(unsigned char data); + +#if SPI_FLASH_USE_DMA +static uint8_t dummy = 0; +static uint8_t _spi_flash_buffer[SECTOR_SIZE]; +#endif /********************** hardware *************************************/ /* SPI_FLASH_CS PA4 */ @@ -18,19 +32,102 @@ static void GPIO_Configuration(void) { GPIO_InitTypeDef GPIO_InitStructure; - RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE); + RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; - GPIO_Init(GPIOA,&GPIO_InitStructure); + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); FLASH_RST_0(); // RESET FLASH_CS_1(); FLASH_RST_1(); } -static unsigned char SPI_HostReadByte(void) +#if SPI_FLASH_USE_DMA +static void DMA_RxConfiguration(rt_uint32_t addr, rt_size_t size) +{ + DMA_InitTypeDef DMA_InitStructure; + + DMA_ClearFlag(DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_TC3 | DMA1_FLAG_TE3); + dummy = 0; + + /* DMA Channel configuration ----------------------------------------------*/ + DMA_Cmd(DMA1_Channel2, DISABLE); + DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI1->DR)); + DMA_InitStructure.DMA_MemoryBaseAddr = (u32) addr; + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; + DMA_InitStructure.DMA_BufferSize = size; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; + DMA_Init(DMA1_Channel2, &DMA_InitStructure); + + DMA_Cmd(DMA1_Channel2, ENABLE); + + /* Dummy TX channel configuration */ + DMA_Cmd(DMA1_Channel3, DISABLE); + DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI1->DR)); + DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(&dummy); + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; + DMA_InitStructure.DMA_BufferSize = size; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; + DMA_Init(DMA1_Channel3, &DMA_InitStructure); + + DMA_Cmd(DMA1_Channel3, ENABLE); +} + +static void DMA_TxConfiguration(rt_uint32_t addr, rt_size_t size) +{ + DMA_InitTypeDef DMA_InitStructure; + + DMA_ClearFlag(DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_TC3 | DMA1_FLAG_TE3); + + /* DMA Channel configuration ----------------------------------------------*/ + DMA_Cmd(DMA1_Channel2, DISABLE); + DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI1->DR)); + DMA_InitStructure.DMA_MemoryBaseAddr = (u32)(&dummy); + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; + DMA_InitStructure.DMA_BufferSize = size; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; + DMA_Init(DMA1_Channel2, &DMA_InitStructure); + + /* DMA Channel configuration ----------------------------------------------*/ + DMA_Cmd(DMA1_Channel3, DISABLE); + DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)(&(SPI1->DR)); + DMA_InitStructure.DMA_MemoryBaseAddr = (u32) addr; + DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; + DMA_InitStructure.DMA_BufferSize = size; + DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; + DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; + DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; + DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; + DMA_InitStructure.DMA_Priority = DMA_Priority_Medium; + DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; + DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; + DMA_Init(DMA1_Channel3, &DMA_InitStructure); + + DMA_Cmd(DMA1_Channel3, ENABLE); +} +#endif + +static uint8_t SPI_HostReadByte(void) { //return SPI_WriteByte(0x00); //Wait until the transmit buffer is empty @@ -47,7 +144,7 @@ static unsigned char SPI_HostReadByte(void) } -static void SPI_HostWriteByte(unsigned char wByte) +static void SPI_HostWriteByte(uint8_t wByte) { SPI_WriteByte(wByte); } @@ -63,13 +160,13 @@ static void SPI_HostWriteByte(unsigned char wByte) /* 1:ready | | AT45DB161:1011 | */ /* --------------------------------------------------------------------------*/ /*****************************************************************************/ -static unsigned char AT45DB_StatusRegisterRead(void) +static uint8_t AT45DB_StatusRegisterRead(void) { - unsigned char i; + uint8_t i; FLASH_CS_0(); SPI_HostWriteByte(AT45DB_READ_STATE_REGISTER); - i=SPI_HostReadByte(); + i = SPI_HostReadByte(); FLASH_CS_1(); return i; @@ -77,74 +174,122 @@ static unsigned char AT45DB_StatusRegisterRead(void) static void wait_busy(void) { - unsigned int i=0; - while (i++<3000) + uint16_t i = 0; + while (i++ < 10000) { - if (AT45DB_StatusRegisterRead()&0x80) + if (AT45DB_StatusRegisterRead() & 0x80) { - break; + return; } } - if( !(i<3000) ) - { - rt_kprintf("\r\nSPI_FLASH timeout!!!"); - } + rt_kprintf("\r\nSPI_FLASH timeout!!!\r\n"); } -static void read_page(unsigned int page,unsigned char * pHeader) +static void read_page(uint32_t page, uint8_t *pHeader) { - unsigned int i=0; +#if SPI_FLASH_USE_DMA + rt_sem_take(&spi1_lock, RT_WAITING_FOREVER); - wait_busy(); + DMA_RxConfiguration((rt_uint32_t) pHeader, SECTOR_SIZE); FLASH_CS_0(); - SPI_HostWriteByte(AT45DB_MM_PAGE_TO_B1_XFER); - SPI_HostWriteByte((unsigned char)(page >> 6)); - SPI_HostWriteByte((unsigned char)(page << 2)); - SPI_HostWriteByte(0x00); - FLASH_CS_1(); - wait_busy(); + SPI_HostWriteByte(AT45DB_MM_PAGE_READ); + SPI_HostWriteByte((uint8_t)(page >> 6)); + SPI_HostWriteByte((uint8_t)(page << 2)); + SPI_HostWriteByte(0x00); + + // 4 don't care bytes + SPI_HostWriteByte(0x00); + SPI_HostWriteByte(0x00); + SPI_HostWriteByte(0x00); + SPI_HostWriteByte(0x00); + + SPI_I2S_ClearFlag(SPI1, SPI_I2S_FLAG_RXNE); + SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE); + while (DMA_GetFlagStatus(DMA1_FLAG_TC2) == RESET); + + FLASH_CS_1(); + + SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, DISABLE); + + rt_sem_release(&spi1_lock); +#else + uint16_t i; + + rt_sem_take(&spi1_lock, RT_WAITING_FOREVER); FLASH_CS_0(); - SPI_HostWriteByte(AT45DB_BUFFER_1_READ); - SPI_HostWriteByte(0x00); - SPI_HostWriteByte(0x00); - SPI_HostWriteByte(0x00); - SPI_HostWriteByte(0x00); - for (i=0; i<512; i++) - { - *pHeader++ = SPI_HostReadByte(); - } - FLASH_CS_1(); + SPI_HostWriteByte(AT45DB_MM_PAGE_READ); + SPI_HostWriteByte((uint8_t)(page >> 6)); + SPI_HostWriteByte((uint8_t)(page << 2)); + SPI_HostWriteByte(0x00); + + // 4 don't care bytes + SPI_HostWriteByte(0x00); + SPI_HostWriteByte(0x00); + SPI_HostWriteByte(0x00); + SPI_HostWriteByte(0x00); + + for (i = 0; i < SECTOR_SIZE; i++) + { + *pHeader++ = SPI_HostReadByte(); + } + + FLASH_CS_1(); + + rt_sem_release(&spi1_lock); +#endif } -static void write_page(unsigned int page,unsigned char * pHeader) +static void write_page(uint32_t page, uint8_t *pHeader) { - unsigned int i; +#if SPI_FLASH_USE_DMA + rt_sem_take(&spi1_lock, RT_WAITING_FOREVER); + + DMA_TxConfiguration((rt_uint32_t) pHeader, SECTOR_SIZE); + + FLASH_CS_0(); + + SPI_HostWriteByte(AT45DB_MM_PAGE_PROG_THRU_BUFFER1); + SPI_HostWriteByte((uint8_t) (page >> 6)); + SPI_HostWriteByte((uint8_t) (page << 2)); + SPI_HostWriteByte(0x00); + + SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); + while (DMA_GetFlagStatus(DMA1_FLAG_TC3) == RESET); + + FLASH_CS_1(); + + SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, DISABLE); wait_busy(); + rt_sem_release(&spi1_lock); +#else + uint16_t i; + + rt_sem_take(&spi1_lock, RT_WAITING_FOREVER); + FLASH_CS_0(); - SPI_HostWriteByte(AT45DB_BUFFER_2_WRITE); - SPI_HostWriteByte(0); - SPI_HostWriteByte(0); - SPI_HostWriteByte(0); - for(i=0; i<512; i++) + + SPI_HostWriteByte(AT45DB_MM_PAGE_PROG_THRU_BUFFER1); + SPI_HostWriteByte((uint8_t) (page >> 6)); + SPI_HostWriteByte((uint8_t) (page << 2)); + SPI_HostWriteByte(0x00); + + for (i = 0; i < SECTOR_SIZE; i++) { SPI_HostWriteByte(*pHeader++); } + FLASH_CS_1(); wait_busy(); - FLASH_CS_0(); - SPI_HostWriteByte(AT45DB_B2_TO_MM_PAGE_PROG_WITH_ERASE); - SPI_HostWriteByte((unsigned char)(page>>6)); - SPI_HostWriteByte((unsigned char)(page<<2)); - SPI_HostWriteByte(0x00); - FLASH_CS_1(); + rt_sem_release(&spi1_lock); +#endif } @@ -176,42 +321,53 @@ static rt_err_t rt_spi_flash_control(rt_device_t dev, rt_uint8_t cmd, void *args static rt_size_t rt_spi_flash_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { - rt_uint8_t *ptr; rt_uint32_t index, nr; - nr = size/512; - ptr = (rt_uint8_t*)buffer; + nr = size / SECTOR_SIZE; - for (index = 0; index < nr; index ++) + for (index = 0; index < nr; index++) { /* only supply single block read: block size 512Byte */ - read_page((pos + index * 512)/512, &ptr[index * 512]); +#if SPI_FLASH_USE_DMA + read_page((pos / SECTOR_SIZE + index), _spi_flash_buffer); + rt_memcpy(((rt_uint8_t *) buffer + index * SECTOR_SIZE), _spi_flash_buffer, SECTOR_SIZE); +#else + read_page((pos / SECTOR_SIZE + index), ((rt_uint8_t *) buffer + index * SECTOR_SIZE)); +#endif } - return nr * 512; + return nr * SECTOR_SIZE; } -static rt_size_t rt_spi_flash_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) +static rt_size_t rt_spi_flash_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size) { - rt_uint8_t *ptr; rt_uint32_t index, nr; - nr = size / 512; - ptr = (rt_uint8_t*)buffer; + nr = size / SECTOR_SIZE; - for (index = 0; index < nr; index ++) + for (index = 0; index < nr; index++) { /* only supply single block write: block size 512Byte */ - write_page((pos + index * 512)/512, &ptr[index * 512]); +#if SPI_FLASH_USE_DMA + rt_memcpy(_spi_flash_buffer, ((rt_uint8_t *) buffer + index * SECTOR_SIZE), SECTOR_SIZE); + write_page((pos / SECTOR_SIZE + index), _spi_flash_buffer); +#else + write_page((pos / SECTOR_SIZE + index), ((rt_uint8_t *) buffer + index * SECTOR_SIZE)); +#endif } - return nr * 512; + return nr * SECTOR_SIZE; } void rt_hw_spi_flash_init(void) { GPIO_Configuration(); +#if SPI_FLASH_USE_DMA + /* Enable the DMA1 Clock */ + RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); +#endif + /* register spi_flash device */ spi_flash_device.type = RT_Device_Class_Block; spi_flash_device.init = rt_spi_flash_init; diff --git a/bsp/stm32_radio/spi_flash.h b/bsp/stm32_radio/spi_flash.h index 1c57e93d88..66a38285fe 100644 --- a/bsp/stm32_radio/spi_flash.h +++ b/bsp/stm32_radio/spi_flash.h @@ -18,7 +18,8 @@ thanks to gxlujd. #define AT45DB_PAGE_ERASE 0x81 /* ҳɾ³ý£¨Ã¿Ò³512/528×Ö½Ú£© */ #define AT45DB_SECTOR_ERASE 0x7C /* ÉÈÇø²Á³ý£¨Ã¿ÉÈÇø128K×Ö½Ú£©*/ #define AT45DB_READ_STATE_REGISTER 0xD7 /* ¶Áȡ״̬¼Ä´æÆ÷ */ - +#define AT45DB_MM_PAGE_READ 0xD2 /* ¶ÁÈ¡Ö÷´¢´æÆ÷µÄÖ¸¶¨Ò³ */ +#define AT45DB_MM_PAGE_PROG_THRU_BUFFER1 0x82 /* ͨ¹ý»º³åÇøдÈëÖ÷´¢´æÆ÷ */ extern void rt_hw_spi_flash_init(void);