📄 utility.c
字号:
/************************************************** * * utility.c * * CVS ID: $Id: utility.c,v 1.26 2007/09/21 05:35:42 hara Exp $ * Author: Raffaele Belardi [RB] - STM * Date: $Date: 2007/09/21 05:35:42 $ * Revision: $Revision: 1.26 $ * * Description: * * *************************************************** * * COPYRIGHT (C) ST Microelectronics 2005 * All Rights Reserved * *************************************************** * * STM CVS Log: * * $Log: utility.c,v $ * Revision 1.26 2007/09/21 05:35:42 hara * Initial implementation for WMDRM feature into A+. * * Revision 1.25 2007/08/01 15:26:34 belardi * Modifications to support run-time configurable ESP size * - when ESP is disabled, allocate all memory to X_array except 9 sectors for ESP * * Revision 1.24 2007/08/01 10:19:45 belardi * Modifications to support run-time configurable ESP size * - calculation of the ESP thresholds based on ESP size * * Revision 1.23 2007/02/06 11:13:37 belardi * Added dynamic remapping of SDRAM for ESP vs. X_array * * Revision 1.22 2007/02/02 17:27:10 belardi * Added config item to increase X_array for 15000 files support. Breaks CDDA and CDROM (sound like FF) * * Revision 1.21 2006/12/19 11:05:02 belardi * Integration of Optomech AAC decode P061219 * * Revision 1.20 2006/11/28 09:28:27 belardi * m4a decoder alfa release from Optomech * - using free SDRAM foe first frame of m4a * * Revision 1.19 2006/10/24 09:31:33 belardi * Code rearrangement to fix system hang when HAVE_EXTERNAL_XARRAY=0 * * Revision 1.18 2006/10/23 13:46:27 belardi * Added #include to remove compier warning * * Revision 1.17 2006/10/23 09:01:24 marcucci * Add functions to Enable/Disable Global Interrupt for ctr_update_transition * * Revision 1.16 2006/10/18 09:55:03 trubac * bug fix for no external X_array * * Revision 1.15 2006/10/05 07:33:56 trubac * Implementing TOC info at the end of string pool * * Revision 1.14 2006/09/19 16:08:24 belardi * Redefinition of the abort() to avoid pulling in the library * * Revision 1.13 2006/09/18 09:55:23 belardi * Corrected CVS keyword usage * * Revision 1.12 2006/09/18 09:24:43 belardi * Added Log CVS keyword into file header * * ***************************************************/#include "gendef.h"#include "hwreg.h"#include "audiobuffer.h" //[MM]#include "capture.h" //[MM]#include "text.h" //[MM]#include "xfile.h"#if (0 != HAVE_AAC)#include "audiodec.h"#include "aacwrap.h"#endif /* HAVE_AAC */#include "utility.h"#include "lld_eic.h"#include "mconfig.h"/******************************************************************************//* Function: configure_gpio *//* *//*! \brief Configure the GPIO bits * \param[in] port PORT_A or PORT_B * \param[in] bit Integer ranging 0..8 * \param[in] function * \return void * \remark *//******************************************************************************/void configure_gpio(unsigned int port, unsigned int bit, unsigned int function){ unsigned int onebit; volatile uint32 *pc0_addr; volatile uint32 *pc1_addr; volatile uint32 *pc2_addr; onebit = 1; if(port == PORT_A) { pc0_addr = &PC0A; pc1_addr = &PC1A; pc2_addr = &PC2A; } else { pc0_addr = &PC0B; pc1_addr = &PC1B; pc2_addr = &PC2B; } onebit = onebit << bit; switch(function) { case GPIO_AF_PP: *pc0_addr |= onebit; // 1 *pc1_addr |= onebit; // 1 *pc2_addr |= onebit; // 1 break; case GPIO_AF_OD: *pc0_addr &= ~onebit; // 0 *pc1_addr |= onebit; // 1 *pc2_addr |= onebit; // 1 break; case GPIO_OUT_PP: *pc0_addr |= onebit; // 1 *pc1_addr &= ~onebit; // 0 *pc2_addr |= onebit; // 1 break; case GPIO_OUT_OD: *pc0_addr &= ~onebit; // 0 *pc1_addr &= ~onebit; // 0 *pc2_addr |= onebit; // 1 break; case GPIO_IN_OUT: *pc0_addr |= onebit; // 1 *pc1_addr |= onebit; // 1 *pc2_addr &= ~onebit; // 0 break; case GPIO_IN: *pc0_addr |= onebit; // 1 *pc1_addr &= ~onebit; // 0 *pc2_addr &= ~onebit; // 0 break; default: break; }}void set_gpio(unsigned int port, unsigned int bit, unsigned int val){ unsigned int onebit; volatile uint32 *pd_addr; onebit = 1; if(port) { pd_addr = &PDA; } else { pd_addr = &PDB; } onebit = onebit << bit; if(val) { *pd_addr |= onebit; } else { *pd_addr &= ~onebit; }}void SetUpDMA(uint32 DmaCh, uint32 * Source, uint32 * Dest, uint32 SourceWordSize, uint32 DestWordSize, uint32 WordsNo, uint32 BurstSize, uint32 SourceInc, uint32 DestInc, uint32 Per, uint32 Mem2Mem){ switch(DmaCh) { case DMA_CH0: DMA_SOURCE_LO0 = (uint32) Source; DMA_SOURCE_HI0 = (uint32) (((uint32) Source) >> 16); DMA_DEST_LO0 = (uint32) Dest; DMA_DEST_HI0 = (uint32) (((uint32) Dest) >> 16); DMA_CTRL0.field.dir = Per; // Peripheral is The Source DMA_CTRL0.field.soburst = BurstSize; DMA_CTRL0.field.sosize = SourceWordSize; DMA_CTRL0.field.soinc = SourceInc; // Source Register Unchanged DMA_CTRL0.field.deinc = DestInc; // Increment Destination Address DMA_CTRL0.field.desize = DestWordSize; // Destination Word Size : 32 Bits //DMA_MAX0 = (WordsNo >> SourceWordSize); DMA_MAX0 = WordsNo >> 2; break; case DMA_CH1: DMA_SOURCE_LO1 = (uint32) Source; DMA_SOURCE_HI1 = (uint32) (((uint32) Source) >> 16); DMA_DEST_LO1 = (uint32) Dest; DMA_DEST_HI1 = (uint32) (((uint32) Dest) >> 16); DMA_CTRL1.field.dir = Per; // Peripheral is The Source DMA_CTRL1.field.soburst = BurstSize; DMA_CTRL1.field.sosize = SourceWordSize; DMA_CTRL1.field.soinc = SourceInc; // Source Register Unchanged DMA_CTRL1.field.deinc = DestInc; // Increment Destination Address DMA_CTRL1.field.desize = DestWordSize; // Destination Word Size : 32 Bits DMA_MAX1 = (WordsNo >> 2); break; case DMA_CH2: DMA_SOURCE_LO2 = (uint32) Source; DMA_SOURCE_HI2 = (uint32) (((uint32) Source) >> 16); DMA_DEST_LO2 = (uint32) Dest; DMA_DEST_HI2 = (uint32) (((uint32) Dest) >> 16); DMA_CTRL2.field.dir = Per; // Peripheral is The Source DMA_CTRL2.field.soburst = BurstSize; DMA_CTRL2.field.sosize = SourceWordSize; DMA_CTRL2.field.soinc = SourceInc; // Source Register Unchanged DMA_CTRL2.field.deinc = DestInc; // Increment Destination Address DMA_CTRL2.field.desize = DestWordSize; // Destination Word Size : 32 Bits DMA_MAX2 = (WordsNo); break; case DMA_CH3: DMA_SOURCE_LO3 = (uint32) Source; DMA_SOURCE_HI3 = (uint32) (((uint32) Source) >> 16); DMA_DEST_LO3 = (uint32) Dest; DMA_DEST_HI3 = (uint32) (((uint32) Dest) >> 16); DMA_CTRL3.field.dir = Per; // Peripheral is The Source DMA_CTRL3.field.soburst = BurstSize; DMA_CTRL3.field.sosize = SourceWordSize; DMA_CTRL3.field.soinc = SourceInc; // Source Register Unchanged DMA_CTRL3.field.deinc = DestInc; // Increment Destination Address DMA_CTRL3.field.desize = DestWordSize; // Destination Word Size : 32 Bits DMA_MAX3 = WordsNo; DMA_CTRL3.field.mem2mem = Mem2Mem; break; default: break; }}void SetDMAChannel(uint32 channel_no, uint32 source){ switch(channel_no) { case 0: GCR3.field.dma_ch0_src_sel = source; break; case 1: GCR3.field.dma_ch1_src_sel = source; break; case 2: GCR3.field.dma_ch2_src_sel = source; break; case 3: GCR3.field.dma_ch3_src_sel = source; break; }}uint32 sdram_end_address;void sdram_malloc_init(uint32 start_address){ // 8 bytes boundary Alignment sdram_end_address = (start_address + 7) & (~7); }uint32 sdram_malloc(uint32 size){ uint32 ptr; ptr = sdram_end_address; sdram_end_address = sdram_end_address + size; // Execute this check here before 4 bytes boundary aligmnent // beacuse it could be possible to have space for the last element if(sdram_end_address < 0x80200000) { // Eight byte Boundary Aligment for the // next memory allocation sdram_end_address = (sdram_end_address + 7) & (~7); } else { ptr = 0; } return ptr;}uint32 sdram_layout(uint8 esp_size){#if (0 == HAVE_EXTERNAL_XARRAY) X_array = &X_memory.X_arr[0]; XB_TOC = &X_memory.X_toc; #endif#if (1 == HAVE_SHOCK_MEMORY) uint32 ptr; sdram_malloc_init(0x80000000);#if (1 == HAVE_EXTERNAL_XARRAY) /* values for 2Mbyte SDRAM */ if (esp_size == 0) { XFILE_NODES_NUM = 115760; } else { /* minimum tested CAP buffer with ESP_on is 3s, so scale down requested esp_size */ XFILE_NODES_NUM = (81920 - 2000) * (1 - (float)(esp_size-3)/(DFLT_ESP_SIZE-3)) + 2000; } ptr = sdram_malloc(sizeof(t_XBTOC)+sizeof(t_XNode)*XFILE_NODES_NUM); if(ptr) { X_array = (t_XNode*)ptr; XB_TOC = (t_XBTOC*)(X_array+XFILE_NODES_NUM); } else { return 0; }#endif#if (1==HAVE_CDTEXT) ptr = sdram_malloc(CD_TEXT_SDRAMBUFFERSIZE); if(ptr) { cd_text_sdram_buffer = (uint8*)ptr; } else { return 0; }#endif#if (1==HAVE_WMDRM_LARGE_BUFFER) && (1==HAVE_WMDRM_H10_WORKAROUND) /* Only H10 device, it should prepare more AudioBufferElement for WMDRM high rate song. */ AudioBufferElements = 4;#else AudioBufferElements = 2;#endif ptr = sdram_malloc(sizeof(AudioBufferElement)*AudioBufferElements); if(ptr) { AudioBuffer = (AudioBufferElement *)ptr; } else { return 0; } /* values for 2Mbyte SDRAM */ // [RB] values below chosen to maintain same ratios as in original // [RB] non-configurable implementation by [FB] // [RB] They might not be optimal but I don't know better if (esp_size == 0) { CAP_INPUT_BUFFER_SIZE_SDRAM = CAP_INPUT_BUFFER_SIZE_INTRAM; /* thresholds are hard-coded in cap_config_esp_params_off() */ } else if (esp_size == 3) { /* minimum CAP buffer size in original code was 220 sectors. I don't know why but I keep it */ CAP_INPUT_BUFFER_SIZE_SDRAM = 220; // 2.93 s CAP_ESP_ON_OVERFLOW_THRS = 200; // 2.6 s CAP_ESP_ON_UNDERFLOW_THRS = 2*75; // 2 s } else { /* minimum CAP buffer is 3s, so scale down requested esp_size */ CAP_INPUT_BUFFER_SIZE_SDRAM = (720 - 220) * ((float)(esp_size-3)/(DFLT_ESP_SIZE-3)) + 220; CAP_ESP_ON_OVERFLOW_THRS = (CAP_INPUT_BUFFER_SIZE_SDRAM * 0.94); // keep same ratio as values originally defined by [FB] CAP_ESP_ON_UNDERFLOW_THRS = (150 + (esp_size - 3) * 63); // scale linearly from 2s to 7s. 63=0.84*75=5sec/6slots*75 } CAP_CHIN_SECTOR_SIZE = 2560; ptr = sdram_malloc(CAP_INPUT_BUFFER_SIZE_SDRAM*CAP_CHIN_SECTOR_SIZE); if(ptr) { cap_input_buffer_SDRAM = (uint8 *)ptr; } else { return 0; }#if (0 != HAVE_AAC) AACIndexSize = (0x801FFFFF - sdram_end_address) & ~7; ptr = sdram_malloc(AACIndexSize); if(ptr) { AACIndexBuffer = (uint8 *)ptr; } else { AACIndexBuffer = NULL; AACIndexSize = 0; }#endif /* HAVE_AAC */ #endif return 1;}void exception_hdl(void){ uint32 i; // The right formula seems to be // (PR+1)*(TV+1)* (sytem_clock*4) = T // System Clock = 14nsec at 67Mhz // T in sec. // As WDT //configure_gpio(PORT_A, GPIO_7, GPIO_OUT_PP); // CTL1 //PDA |= 0x80; AAB_PUR0.field.wdg = 1; // Bit 1 AAB_PCG0.field.wdg = 1; // Bit 1 for(i=0; i<100; i++); WDT_CR.field.we = 0; // Timer is disabled WDT_PR = 16; WDT_VR = 1; WDT_MR = 0; //PDA &= (~0x80); WDT_CR.field.we = 1; // WDT while(1); //Wait for reset }/* [RB] 19 Sep 2006 *//* Redefinition of the ARM libray's 'abort' function, which uses semihosting swi *//* abort() is called only from the WMA library routines */void abort(void){ exception_hdl();}uint32 intreg;void dis_interrupts(void) { intreg = EIC_vEicGlobalDis();}void en_interrupts(void){ EIC_vEicGlobalRest(intreg); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -