快樂蝦
http://blog.csdn.net/lights_joy/
lights@hb165.com
本文適用于
ADI bf561 DSP
uclinux-2008r1.5-rc3(smp patch)
Visual DSP++ 5.0(update 5)
歡迎轉載,但請保留作者信息
本文討論鏈接: http://www.bfin-tools.org/bbs/viewthread.php?tid=20&extra =
在之前的處理中,只是簡單地給 B 核一條 idle 指令,并讓它先于 A 核運行,現在要開始使用 B 核了,自然這種方式就不好使了。
還記得 ADI 那個經典的 Set_PLL 嗎?呵呵,看看:
void Set_PLL( short CoreCLOCK_multiplier, short SCLK_divider)
{ short previous_PLL= *pPLL_CTL;
short previous_SICA_IWR = *pSICA_IWR0;
short previous_SICB_IWR = *pSICB_IWR0;
short new_PLL= (previous_PLL & 0x81ff) | ((CoreCLOCK_multiplier & 0x3f) <<9);
if (new_PLL != previous_PLL) { // skip if multiplier has not changed
if (( int )(*pSRAM_BASE_ADDRESS) == 0xFF800000 ) { // do things for Core A
*pSICB_SYSCR |= 0x0080; // Raise Core B Supplemental-Int0
ssync();
while ((*pSICB_SYSCR & 0x080)) { // Wait: Core B Acknowledge SUP-B0
asm volatile ( "nop;nop;nop;nop;" );
}
*pSICA_IWR0 = (previous_SICA_IWR | 0x1); // enable PLL Wakeup Interrupt
*pPLL_CTL = new_PLL;
ssync();
idle(); // put in idle
*pSICA_IWR0 = previous_SICA_IWR; // continue here after idle, restore previous IWR content
ssync();
}
else { // do things for Core B
while (!(*pSICB_SYSCR & 0x0080)) { // Wait: For Core A to raise SUP-B0
asm volatile ( "nop;nop;nop;nop;" );
}
*pSICB_SYSCR = 0x0800; // Acknowledge Supplemental Interrupt
ssync();
*pSICB_IWR0 = (previous_SICB_IWR | 0x1); // enable PLL Wakeup Interrupt
ssync();
idle(); // put in idle
*pSICB_IWR0 = previous_SICB_IWR; // continue here after idle, restore previous IWR content
ssync();
} // if (&_CORE == 0)
} // if (new_PLL != previous_PLL)
*pPLL_DIV = (*pPLL_DIV & 0xFFF0) | SCLK_divider;
ssync();
}
這段代碼無非就是撇開 SICA_SYSCR 中的 CoreB_SRAM_INIT 這一位,改用 SICB_SYSCR 進行核間通信。因為在 VDSP 下 CoreB_SRAM_INIT 這一位總是為 0 的,也就是說 B 核總是運行的。既然如此,我們干脆大方點,一開始就把這一位清 0 。
看看 SICB_SYSCR :
再看看它的使用:
Core A can write “1” to Bit 6 of SICB_SYSCR to interrupt itself or to Bit 7 to interrupt Core B. Similarly, Core B can write “1” to Bit 8 of SICB_SYSCR to interrupt Core A or to Bit 9 to interrupt itself. Writing “1” to Bits 10, 11, 12, 13, respectively, would clear these interrupts.
現在我們學習它的這種方式,在 B 核啟動的時候調用這個函數:
void wait_pll_setup()
{
/* 等待 A 核進行 PLL 配置 */
short previous_SICB_IWR = *pSICB_IWR0;
while (!(*pSICB_SYSCR & 0x0080))
{
// Wait: For Core A to raise SUP-B0
asm volatile ( "nop;nop;nop;nop;" );
}
*pSICB_SYSCR = 0x0800; // Acknowledge Supplemental Interrupt
ssync();
*pSICB_IWR0 = (previous_SICB_IWR | 0x1); // enable PLL Wakeup Interrupt
ssync();
idle(); // put in idle
*pSICB_IWR0 = previous_SICB_IWR; // continue here after idle, restore previous IWR content
ssync();
// 等待真正的啟動信號
while (!(*pSICB_SYSCR & 0x0080))
{
asm volatile ( "nop;nop;nop;nop;" );
}
}
這段代碼將首先等待 A 核的一個中斷,然后進入 IDLE 狀態,這樣 A 核進行的 PLL 設置就可以生效了。然后進入第二次等待,等待真正的啟動信號,這樣 B 核才真正開始執行,這個啟動信號將在 A 核啟動完成后給出,也就是原來要將 SICA_SYSCR 中的 CoreB_SRAM_INIT 這一位清 0 的位置。
在 A 核中,原來進行 PLL 配置是由這幾行代碼實現的:
//p0.h = hi(PLL_CTL);
//p0.l = lo(PLL_CTL); /* Load the address */
//cli r2; /* Disable interrupts */
//ssync;
//w[p0] = r0.l; /* Set the value */
//idle; /* Wait for the PLL to stablize */
//sti r2; /* Enable interrupts */
我們現在改用這個函數來完成:
void notify_pll_setup( unsigned int pll_value)
{
short previous_SICA_IWR = *pSICA_IWR0;
unsigned int mask;
/* The default startup code does not include any functionality to allow core
A to enable core B. A convenient way to enable core B is to use the
'adi_core_b_enable()' function. */
adi_core_b_enable();
*pSICB_SYSCR |= 0x0080; // Raise Core B Supplemental-Int0
ssync();
while ((*pSICB_SYSCR & 0x080))
{
// Wait: Core B Acknowledge SUP-B0
asm volatile ( "nop;nop;nop;nop;" );
}
*pSICA_IWR0 = (previous_SICA_IWR | 0x1); // enable PLL Wakeup Interrupt
ssync();
*pPLL_CTL = pll_value;
ssync();
idle(); // put in idle
*pSICA_IWR0 = previous_SICA_IWR; // continue here after idle, restore previous IWR content
ssync();
}
這段代碼將啟用 B 核,然后給它一個中斷,再等待 B 核的確認,最后再寫入 PLL_CTL 。
這樣在 VDSP 下調試的時候,只要先運行 B 核就可以了。
搞定!
PS:突然想起某君的一篇論文,其實通篇就一句話:“用SICB_SYSCR進行核間通信”,居然也可以包裝出一篇論文來,不得不讓人感嘆包裝的力量,哈哈!!
1 參考資料
uclinux-2008R1.5-RC3(bf561) 到 VDSP5 的移植 (63) : _NSIG_WORDS_is_unsupported_size (2009-2-11)
uclinux-2008R1.5-RC3(bf561) 到 VDSP5 的移植 (64) : __ebss_b_l1 (2009-02-12)
uclinux-2008R1.5-RC3(bf561) 到 VDSP5 的移植 (65) : B 核啟動 (2009-2-13)
uclinux-2008R1.5-RC3(bf561) 到 VDSP5 的移植 (66) : _ebss_l1 (2009-02-13)
uclinux-2008R1.5-RC3(bf561) 到 VDSP5 的移植 (67) : li1240 (2009-2-14)
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
