This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
at91sam7s patch for PIT EFC PMC all in one...
- From: "oliver munz @ s p e a g" <munz at speag dot ch>
- To: ecos-patches at sourceware dot org, Andrew Lunn <andrew at lunn dot ch>
- Date: Thu, 04 Jun 2009 10:43:39 +0200
- Subject: at91sam7s patch for PIT EFC PMC all in one...
- Reply-to: munz at speag dot ch
Hier comes the announced patch:
1. It allows the use of the second flash in the 512k devices.
2. It solves a possible problem with a late PIT-initalisation.
3. It improves the startup-time and prevents changes in the holly
system-clock when booting from a boot-monitor.
4. It removes a spaces at the end of the line.
Index: packages/devs/flash/arm/at91/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/arm/at91/current/ChangeLog,v
retrieving revision 1.9
diff -u -r1.9 ChangeLog
--- packages/devs/flash/arm/at91/current/ChangeLog 3 Nov 2008 08:41:59 -0000 1.9
+++ packages/devs/flash/arm/at91/current/ChangeLog 4 Jun 2009 07:30:43 -0000
@@ -1,3 +1,7 @@
+2009-06-03 Oliver Munz <munz@speag.ch>
+
+ * src/at91_flash.c (Add support for 512kByte-devices.
+
2008-11-03 Gabor Toeroek <tgabor84@gmail.com>
* src/at91_flash.c (flash_hwr_init): Add partial support for
Index: packages/devs/flash/arm/at91/current/src/at91_flash.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/flash/arm/at91/current/src/at91_flash.c,v
retrieving revision 1.9
diff -u -r1.9 at91_flash.c
--- packages/devs/flash/arm/at91/current/src/at91_flash.c 3 Nov 2008 08:41:59 -0000 1.9
+++ packages/devs/flash/arm/at91/current/src/at91_flash.c 4 Jun 2009 07:30:43 -0000
@@ -2,7 +2,7 @@
//
// at91_flash.c
//
-// Flash programming for the at91 devices which have the
+// Flash programming for the at91 devices which have the
// Embedded Flash Controller.
//
//==========================================================================
@@ -41,11 +41,11 @@
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas
-// Contributors: gthomas, dmoseley, Andrew Lunn, Oliver Munz
-// Date: 2000-07-26
-// Purpose:
-// Description:
-//
+// Contributors: gthomas, dmoseley, Andrew Lunn, Oliver Munz, Kasim Malla
+// Date: 2009-06-03
+// Purpose:
+// Description:
+//
//####DESCRIPTIONEND####
//
//==========================================================================
@@ -53,7 +53,7 @@
#include <pkgconf/hal.h>
#include <pkgconf/devs_flash_at91.h>
-#include <cyg/hal/hal_io.h>
+#include <cyg/hal/hal_io.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/infra/cyg_ass.h>
@@ -62,7 +62,8 @@
#include <string.h>
-#define FLASH_TIMEOUT 100000
+#define FLASH_TIMEOUT 100000 /* Stupid timeout depends of the CPU clock speed... */
+#define AT91_FLASH_FMCN_VALUE (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED * 15 / 10000000 + 1)
#ifdef CYGBLD_DEV_FLASH_AT91_LOCKING
static cyg_uint32 sector_size;
@@ -70,50 +71,169 @@
// Disable the flash controller from erasing the page before
// programming it
-static void
+
+#ifdef AT91_MC_FMR1
+ #define PAGE_AT_WITCH_WE_USE_THE_EFC1 1024
+ #define SECTOR_AT_WITCH_WE_USE_THE_EFC1 16
+#endif
+
+
+static void
flash_erase_before_write_disable (void)
{
cyg_uint32 fmr;
-
+
HAL_READ_UINT32(AT91_MC+AT91_MC_FMR, fmr);
fmr = fmr | AT91_MC_FMR_NEBP;
HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR, fmr);
+#ifdef AT91_MC_FMR1 /* or in other words at91sam7x512 */
+ HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR1, fmr);
+#endif
}
// Enable the flash controller to erase the page before programming
// it
-static void
-flash_erase_before_write_enable (void)
+static void
+flash_erase_before_write_enable (void)
{
-
+
cyg_uint32 fmr;
HAL_READ_UINT32(AT91_MC+AT91_MC_FMR, fmr);
fmr = fmr & ~((cyg_uint32) AT91_MC_FMR_NEBP);
HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR, fmr);
+#ifdef AT91_MC_FMR1 /* or in other words at91sam7x512 */
+ HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR1, fmr);
+#endif
+}
+
+#ifdef AT91_MC_FMR1 /* or in other words at91sam7x512 */
+
+// Is the flash controller ready to accept the next command?
+static __inline__ cyg_bool
+flash_controller_is_ready(cyg_uint32 page)
+CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
+
+static __inline__ cyg_bool
+flash_controller_is_ready(cyg_uint32 page)
+{
+ cyg_uint32 fsr;
+
+ if (page < PAGE_AT_WITCH_WE_USE_THE_EFC1){
+ HAL_READ_UINT32(AT91_MC+AT91_MC_FSR, fsr);
+ } else {
+ HAL_READ_UINT32(AT91_MC+AT91_MC_FSR1, fsr);
+ }
+ return (fsr & AT91_MC_FSR_FRDY ? true : false);
+}
+
+// Busy loop waiting for the controller to finish the command.
+// Wait a maximum of timeout loops and then return an error.
+static __inline__ int
+flash_wait_for_controller (cyg_uint32 page, cyg_uint32 timeout)
+CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
+
+static __inline__ int
+flash_wait_for_controller (cyg_uint32 page, cyg_uint32 timeout)
+{
+ while (!flash_controller_is_ready(page)){
+ timeout--;
+ if (!timeout) {
+ return FLASH_ERR_DRV_TIMEOUT;
+ }
+ }
+ return FLASH_ERR_OK;
+}
+
+
+// Execute one command on the flash controller. This code should
+// probably not be in flash
+
+static int
+flash_run_command(cyg_uint32 address,
+ cyg_uint32 command,
+ cyg_uint32 timeout)
+CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
+
+static int
+flash_run_command(cyg_uint32 address,
+ cyg_uint32 command,
+ cyg_uint32 timeout)
+{
+ cyg_uint32 retcode;
+ cyg_uint32 fsr;
+ cyg_uint32 mask;
+ cyg_uint32 page;
+
+ page = ((cyg_uint32) address - (cyg_uint32) flash_info.start) /
+ flash_info.block_size;
+
+ // Wait for the last command to finish
+ retcode = flash_wait_for_controller(page, timeout);
+ if (retcode != FLASH_ERR_OK){
+ return retcode;
+ }
+
+ HAL_DISABLE_INTERRUPTS(mask);
+
+ if (page < PAGE_AT_WITCH_WE_USE_THE_EFC1){
+ HAL_WRITE_UINT32(AT91_MC+AT91_MC_FCR,
+ command |
+ ((page & AT91_MC_FCR_PAGE_MASK) << AT91_MC_FCR_PAGE_SHIFT) |
+ AT91_MC_FCR_KEY);
+ } else {
+ HAL_WRITE_UINT32(AT91_MC+AT91_MC_FCR1,
+ command |
+ (((page - PAGE_AT_WITCH_WE_USE_THE_EFC1) & AT91_MC_FCR_PAGE_MASK) << AT91_MC_FCR_PAGE_SHIFT) |
+ AT91_MC_FCR_KEY);
+ }
+
+ retcode = flash_wait_for_controller(page, timeout);
+
+ HAL_RESTORE_INTERRUPTS(mask);
+
+ if (retcode != FLASH_ERR_OK){
+ return retcode;
+ }
+
+ // Check for an error
+ if (page < PAGE_AT_WITCH_WE_USE_THE_EFC1){
+ HAL_READ_UINT32(AT91_MC+AT91_MC_FSR, fsr);
+ } else {
+ HAL_READ_UINT32(AT91_MC+AT91_MC_FSR1, fsr);
+ }
+
+ if ((fsr & AT91_MC_FSR_LOCKE) == AT91_MC_FSR_LOCKE)
+ return FLASH_ERR_PROTECT;
+ if ((fsr & AT91_MC_FSR_PROGE) == AT91_MC_FSR_PROGE)
+ return FLASH_ERR_PROGRAM;
+
+ return FLASH_ERR_OK;
}
+#else /* not at91sam7x512 */
+
// Is the flash controller ready to accept the next command?
-static __inline__ cyg_bool
-flash_controller_is_ready(void)
+static __inline__ cyg_bool
+flash_controller_is_ready(void)
CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
-static __inline__ cyg_bool
-flash_controller_is_ready(void)
+static __inline__ cyg_bool
+flash_controller_is_ready(void)
{
cyg_uint32 fsr;
-
+
HAL_READ_UINT32(AT91_MC+AT91_MC_FSR, fsr);
return (fsr & AT91_MC_FSR_FRDY ? true : false);
}
// Busy loop waiting for the controller to finish the command.
// Wait a maximum of timeout loops and then return an error.
-static __inline__ int
-flash_wait_for_controller (cyg_uint32 timeout)
+static __inline__ int
+flash_wait_for_controller (cyg_uint32 timeout)
CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
-static __inline__ int
+static __inline__ int
flash_wait_for_controller (cyg_uint32 timeout)
{
while (!flash_controller_is_ready()){
@@ -128,34 +248,34 @@
// Execute one command on the flash controller. This code should
// probably not be in flash
-static int
-flash_run_command(cyg_uint32 address,
- cyg_uint32 command,
- cyg_uint32 timeout)
+static int
+flash_run_command(cyg_uint32 address,
+ cyg_uint32 command,
+ cyg_uint32 timeout)
CYGBLD_ATTRIB_SECTION(".2ram.flash_run_command");
-static int
-flash_run_command(cyg_uint32 address,
- cyg_uint32 command,
- cyg_uint32 timeout)
+static int
+flash_run_command(cyg_uint32 address,
+ cyg_uint32 command,
+ cyg_uint32 timeout)
{
cyg_uint32 retcode;
cyg_uint32 fsr;
cyg_uint32 mask;
cyg_uint32 page;
-
- page = ((cyg_uint32) address - (cyg_uint32) flash_info.start) /
+
+ page = ((cyg_uint32) address - (cyg_uint32) flash_info.start) /
flash_info.block_size;
-
+
// Wait for the last command to finish
retcode = flash_wait_for_controller(timeout);
if (retcode != FLASH_ERR_OK){
return retcode;
}
-
+
HAL_DISABLE_INTERRUPTS(mask);
-
- HAL_WRITE_UINT32(AT91_MC+AT91_MC_FCR,
+
+ HAL_WRITE_UINT32(AT91_MC+AT91_MC_FCR,
command |
((page & AT91_MC_FCR_PAGE_MASK) << AT91_MC_FCR_PAGE_SHIFT) |
AT91_MC_FCR_KEY);
@@ -179,15 +299,18 @@
return FLASH_ERR_OK;
}
+#endif
+
+
// The flash is embedded in the CPU package. So return the chip
// ID. This allows us to determine if the chip is one we support and
// the size of the flash
-int flash_query(void *data)
+int flash_query(void *data)
{
cyg_uint32 chipID1r;
-
+
HAL_READ_UINT32(AT91_DBG+AT91_DBG_C1R, chipID1r);
-
+
memcpy(data, &chipID1r, sizeof(chipID1r));
return FLASH_ERR_OK;
}
@@ -197,14 +320,13 @@
// the number of blocks. The query function returns the chip ID 1
// register which tells us about the CPU we are running on, the flash
// size etc. Use this information to determine we have a valid setup.
-int
+int
flash_hwr_init(void){
cyg_uint32 chipID1r;
cyg_uint32 flash_mode;
- cyg_uint8 fmcn;
cyg_uint32 lock_bits;
-
+
flash_query (&chipID1r);
if ((chipID1r & AT91_DBG_C1R_CPU_MASK) != AT91_DBG_C1R_ARM7TDMI)
@@ -215,10 +337,10 @@
((chipID1r & AT91_DBG_C1R_ARCH_MASK) != AT91_DBG_C1R_ARCH_AT91SAM7XC) &&
((chipID1r & AT91_DBG_C1R_ARCH_MASK) != AT91_DBG_C1R_ARCH_AT91SAM7SExx))
goto out;
-
+
if ((chipID1r & AT91_DBG_C1R_FLASH_MASK) == AT91_DBG_C1R_FLASH_0K)
goto out;
-
+
if ((chipID1r & AT91_DBG_C1R_NVPTYP_MASK) != AT91_DBG_C1R_NVPTYP_ROMFLASH)
{
@@ -243,19 +365,20 @@
flash_info.blocks = 1024;
lock_bits = 16;
break;
+ case AT91_DBG_C1R_FLASH_512K:
+ flash_info.block_size = 256;
#ifdef AT91_MC_FMR1
- case AT91_DBG_C1R_FLASH_512K:
- flash_info.block_size = 256;
- flash_info.blocks = 1024;
- lock_bits = 16;
- (*flash_info.pf)("at91_flash: Only EFC0 is supported for writes and locks");
- //flash_info.blocks = 2048;
- //lock_bits = 32;
- break;
+ flash_info.blocks = 2048;
+ lock_bits = 32;
+#else
+ flash_info.blocks = 1024;
+ lock_bits = 16;
+ (*flash_info.pf)("at91_flash: Only EFC0 is supported for writes and locks");
#endif
- default:
- goto out;
- }
+ break;
+ default:
+ goto out;
+ }
} else {
// if there is both flash & ROM then: ROM=AT91_DBG_C1R_FLASH, flash=AT91_DBG_C1R_FLASH2
switch (chipID1r & AT91_DBG_C1R_FLASH2_MASK) {
@@ -279,44 +402,41 @@
flash_info.blocks = 1024;
lock_bits = 16;
break;
-#ifdef AT91_MC_FMR1
case AT91_DBG_C1R_FLASH2_512K:
flash_info.block_size = 256;
+#ifdef AT91_MC_FMR1
+ flash_info.blocks = 2048;
+ lock_bits = 32;
+#else
flash_info.blocks = 1024;
lock_bits = 16;
(*flash_info.pf)("at91_flash: Only EFC0 is supported for writes and locks");
- //flash_info.blocks = 2048;
- //lock_bits = 32;
- break;
#endif
- default:
- goto out;
- }
+ break;
+ default:
+ goto out;
+ }
}
flash_info.buffer_size = 0;
flash_info.start = (void *) 0x00100000;
- flash_info.end = (void *)(((cyg_uint32) flash_info.start) +
+ flash_info.end = (void *)(((cyg_uint32) flash_info.start) +
flash_info.block_size * flash_info.blocks);
#ifdef CYGBLD_DEV_FLASH_AT91_LOCKING
sector_size = flash_info.block_size * flash_info.blocks / lock_bits;
#endif
// Set the FLASH clock to 1.5 microseconds based on the MCLK. This
// assumes the CPU is still running from the PLL clock as defined in
- // the HAL CDL and the HAL startup code.
- fmcn = CYGNUM_HAL_ARM_AT91_CLOCK_SPEED * 1.5 / 1000000 + 0.999999; // We must round up!
+ // the HAL CDL and the HAL startup code.
HAL_READ_UINT32(AT91_MC+AT91_MC_FMR, flash_mode);
flash_mode = flash_mode & ~AT91_MC_FMR_FMCN_MASK;
- flash_mode = flash_mode | (fmcn << AT91_MC_FMR_FMCN_SHIFT);
+ flash_mode = flash_mode | (AT91_FLASH_FMCN_VALUE << AT91_MC_FMR_FMCN_SHIFT);
HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR, flash_mode);
#ifdef AT91_MC_FMR1
- HAL_READ_UINT32(AT91_MC+AT91_MC_FMR1, flash_mode);
- flash_mode = flash_mode & ~AT91_MC_FMR_FMCN_MASK;
- flash_mode = flash_mode | (fmcn << AT91_MC_FMR_FMCN_SHIFT);
HAL_WRITE_UINT32(AT91_MC+AT91_MC_FMR1, flash_mode);
#endif
-
+
return FLASH_ERR_OK;
-
+
out:
(*flash_info.pf)("Can't identify FLASH, sorry, ChipID1 %x\n",
chipID1r );
@@ -326,26 +446,26 @@
// Erase a block. The flash controller does not have a command to
// erase a block. So instead we setup the controller to do a program
// writing all 0xff with an erase operation first.
-int
-flash_erase_block (volatile unsigned long block)
+int
+flash_erase_block (volatile unsigned long block)
{
cyg_uint32 retcode;
cyg_uint32 *buffer;
cyg_uint32 *end;
-
+
buffer = (cyg_uint32 *) block;
end = (cyg_uint32 *) (block + flash_info.block_size);
-
- while (buffer < end){
+
+ while (buffer < end){
*buffer = (cyg_uint32) 0xffffffff;
buffer++;
}
-
+
flash_erase_before_write_enable();
- retcode = flash_run_command(block,
- AT91_MC_FCR_START_PROG,
+ retcode = flash_run_command(block,
+ AT91_MC_FCR_START_PROG,
FLASH_TIMEOUT);
-
+
return retcode;
}
@@ -354,29 +474,29 @@
// checks that these conditions are upheld. It would be possible to
// perform extra reads and masking operation to support writing to
// none word assigned addresses or not multiple or a word length.
-int
+int
flash_program_buf (volatile unsigned long addr, unsigned long *data, int len)
{
cyg_uint32 retcode;
volatile unsigned long *target;
-
+
CYG_ASSERT(len % 4 == 0, "Only word writes allowed by current code");
CYG_ASSERT(addr % 4 == 0, "Address must be word aligned for current code");
-
+
target = (volatile unsigned long *)addr;
-
+
while (len > 0) {
*target = *data;
data++;
target++;
len = len - sizeof(unsigned long);
}
-
+
flash_erase_before_write_disable();
- retcode = flash_run_command(addr,
- AT91_MC_FCR_START_PROG,
+ retcode = flash_run_command(addr,
+ AT91_MC_FCR_START_PROG,
FLASH_TIMEOUT);
-
+
return retcode;
}
@@ -390,15 +510,24 @@
cyg_uint32 sector;
cyg_uint32 retcode;
cyg_uint32 status;
-
- sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) /
+
+ sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) /
sector_size;
-
+
+#ifdef AT91_MC_FMR1 /* or in other words at91sam7x512 */
+ if (sector < SECTOR_AT_WITCH_WE_USE_THE_EFC1){
+ HAL_READ_UINT32(AT91_MC + AT91_MC_FSR, status);
+ } else {
+ HAL_READ_UINT32(AT91_MC + AT91_MC_FSR1, status);
+ sector = sector - SECTOR_AT_WITCH_WE_USE_THE_EFC1;
+ }
+#else
HAL_READ_UINT32(AT91_MC + AT91_MC_FSR, status);
-
+#endif
+
if (status & (1 << (sector + 16))){
- retcode = flash_run_command(block,
- AT91_MC_FCR_UNLOCK,
+ retcode = flash_run_command(block,
+ AT91_MC_FCR_UNLOCK,
FLASH_TIMEOUT);
return retcode;
} else {
@@ -415,24 +544,33 @@
cyg_uint32 sector;
cyg_uint32 retcode;
cyg_uint32 status;
-
- sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) /
+
+ sector = (((cyg_uint32) block) - (cyg_uint32) flash_info.start) /
sector_size;
+#ifdef AT91_MC_FMR1 /* or in other words at91sam7x512 */
+ if (sector < SECTOR_AT_WITCH_WE_USE_THE_EFC1){
+ HAL_READ_UINT32(AT91_MC + AT91_MC_FSR, status);
+ } else {
+ HAL_READ_UINT32(AT91_MC + AT91_MC_FSR1, status);
+ sector = sector - SECTOR_AT_WITCH_WE_USE_THE_EFC1;
+ }
+#else
HAL_READ_UINT32(AT91_MC + AT91_MC_FSR, status);
-
+#endif
+
if (!(status & (1 << (sector + 16)))){
- retcode = flash_run_command(block,
- AT91_MC_FCR_LOCK,
+ retcode = flash_run_command(block,
+ AT91_MC_FCR_LOCK,
FLASH_TIMEOUT);
-
+
return retcode;
} else {
return FLASH_ERR_OK;
}
}
-#endif
-
+#endif
+
// Map a hardware status to a package error. NOP since the errors are
// already mapped.
int flash_hwr_map_error(int err){
Index: packages/hal/arm/at91/at91sam7s/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/at91/at91sam7s/current/ChangeLog,v
retrieving revision 1.21
diff -u -r1.21 ChangeLog
--- packages/hal/arm/at91/at91sam7s/current/ChangeLog 3 Nov 2008 08:40:01 -0000 1.21
+++ packages/hal/arm/at91/at91sam7s/current/ChangeLog 4 Jun 2009 07:30:50 -0000
@@ -1,3 +1,8 @@
+2009-06-03 Oliver Munz oli@snr.ch
+ * Fix the the problem of switching the PCM-settings if
+ the PCM is allready up. And impruve the flash-controller
+ programming.
+
2009-11-03 Gabor Toeroek <tgabor84@gmail.com>
* cdl/hal_arm_at91sam7s.cdl
Index: packages/hal/arm/at91/at91sam7s/current/include/hal_platform_setup.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/at91/at91sam7s/current/include/hal_platform_setup.h,v
retrieving revision 1.5
diff -u -r1.5 hal_platform_setup.h
--- packages/hal/arm/at91/at91sam7s/current/include/hal_platform_setup.h 2 Sep 2008 05:37:51 -0000 1.5
+++ packages/hal/arm/at91/at91sam7s/current/include/hal_platform_setup.h 4 Jun 2009 07:30:50 -0000
@@ -43,10 +43,10 @@
//#####DESCRIPTIONBEGIN####
//
// Author(s): gthomas
-// Contributors:gthomas, asl
-// Date: 2006-02-18
+// Contributors:gthomas, asl, Oliver Munz
+// Date: 2009-06-03
// Purpose: AT91SAM7S platform specific support routines
-// Description:
+// Description:
// Usage: #include <cyg/hal/hal_platform_setup.h>
//
//####DESCRIPTIONEND####
@@ -56,79 +56,109 @@
#include <cyg/hal/var_io.h>
#include <cyg/hal/plf_io.h>
-// Macro to initialise the Memory Controller
- .macro _flash_init
-__flash_init__:
- ldr r0,=AT91_MC
+#ifdef CYG_HAL_STARTUP_ROM
+
+
+#define AT91_FLASH_FMCN_VALUE (CYGNUM_HAL_ARM_AT91_CLOCK_SPEED * 15 / 10000000 + 1)
+#if defined(CYGNUM_HAL_ARM_AT91_CLOCK_TYPE_EXTCLOCK)
+# define AT91_PMC_MOR_VALUE (AT91_PMC_MOR_OSCBYPASS)
+#else
+# define AT91_PMC_MOR_VALUE (AT91_PMC_MOR_OSCCOUNT(CYGNUM_HAL_ARM_AT91_PMC_MOR_OSCCOUNT) | AT91_PMC_MOR_MOSCEN)
+#endif
+#define AT91_PMC_PLLR_VALUE (AT91_PMC_PLLR_DIV(CYGNUM_HAL_ARM_AT91_PLL_DIVIDER) | AT91_PMC_PLLR_PLLCOUNT(CYGNUM_HAL_ARM_AT91_PLL_COUNT) | AT91_PMC_PLLR_MUL(CYGNUM_HAL_ARM_AT91_PLL_MULTIPLIER-1) | AT91_PMC_PLLR_USBDIV_1)
+#define AT91_PMC_MCKR_VALUE (AT91_PMC_MCKR_PRES_CLK_2 | AT91_PMC_MCKR_PLL_CLK)
+
+#define AT91_PMC_FLASH_VALUE_SLOW (AT91_MC_FMR_2FWS | (AT91_FLASH_FMCN_VALUE << AT91_MC_FMR_FMCN_SHIFT))
#if CYGNUM_HAL_ARM_AT91_CLOCK_SPEED > 60000000
// When the clock is running faster than 60MHz we need two wait states
- ldr r1,=(AT91_MC_FMR_2FWS)
-#else
-# if CYGNUM_HAL_ARM_AT91_CLOCK_SPEED > 30000000
+# define AT91_PMC_FLASH_VALUE AT91_PMC_FLASH_VALUE_SLOW
+#else
+# if CYGNUM_HAL_ARM_AT91_CLOCK_SPEED > 30000000
// When the clock is running faster than 30MHz we need a wait state
- ldr r1,=(AT91_MC_FMR_1FWS)
-# else
+# define AT91_PMC_FLASH_VALUE (AT91_MC_FMR_1FWS | (AT91_FLASH_FMCN_VALUE << AT91_MC_FMR_FMCN_SHIFT))
+# else
// We have a slow clock, no extra wait states are needed
- ldr r1,=AT91_MC_FMR_0FWS
-# endif
+# define AT91_PMC_FLASH_VALUE (AT91_MC_FMR_0FWS | (AT91_FLASH_FMCN_VALUE << AT91_MC_FMR_FMCN_SHIFT))
+# endif
#endif
+
+
+
+// Macro whit subroutines
+ .macro _subroutines
+ b subroutines_end
+
+
+set_flash_from_r1:
+ push {lr}
+ ldr r0,=AT91_MC
str r1,[r0,#AT91_MC_FMR]
#if defined(AT91_MC_FMR1)
- // If we have a second flash controller we need to set that up as well
str r1,[r0,#AT91_MC_FMR1]
#endif
+ pop {pc}
+
+
+wait_for_flag_pcm_r0r1:
+ push {r2, lr}
+wait_loop:
+ ldr r2,[r0,#AT91_PMC_SR]
+ ands r2,r1,r2
+ beq wait_loop
+ pop {r2, pc}
+
+
+subroutines_end:
.endm
+
+
+
+
// Macro to start the main clock.
.macro _main_clock_init
__main_clock_init__:
ldr r0,=AT91_PMC
- // Check that we have a stable clock before we start switching
-wait_pmc_sr_0:
- ldr r1,[r0,#AT91_PMC_SR]
- ands r1,r1,#AT91_PMC_SR_MCKRDY
- beq wait_pmc_sr_0
-
- // Swap to the slow clock, just to be sure.
- ldr r1,=(AT91_PMC_MCKR_PRES_CLK|AT91_PMC_MCKR_SLOW_CLK)
- str r1,[r0,#AT91_PMC_MCKR]
-
-#if defined(CYGNUM_HAL_ARM_AT91_CLOCK_TYPE_EXTCLOCK)
- ldr r1,=(AT91_PMC_MOR_OSCBYPASS)
-#else
- ldr r1,=(AT91_PMC_MOR_OSCCOUNT(CYGNUM_HAL_ARM_AT91_PMC_MOR_OSCCOUNT)|AT91_PMC_MOR_MOSCEN)
-#endif
- str r1,[r0,#AT91_PMC_MOR]
-
+ ldr r2,=AT91_PMC_MOR_VALUE // Load our PMC settings in registers
+ ldr r3,=AT91_PMC_PLLR_VALUE
+ ldr r4,=AT91_PMC_MCKR_VALUE
+
+ ldr r5,[r0,#AT91_PMC_MOR] // Test if the PMC is allready up
+ cmp r2, r5
+ bne set_pcm_registers // Do the init
+ ldr r5,[r0,#AT91_PMC_PLLR]
+ cmp r3, r5
+ bne set_pcm_registers // Do the init
+ ldr r5,[r0,#AT91_PMC_MCKR]
+ cmp r4, r5
+ bne set_pcm_registers // Do the init
+ b pmc_done // All registers are where we want it...
+
+ // We have to set the PMC
+set_pcm_registers:
+ str r2,[r0,#AT91_PMC_MOR]
// Wait for oscilator start timeout
-wait_pmc_sr_1:
- ldr r1,[r0,#AT91_PMC_SR]
- ands r1,r1,#AT91_PMC_SR_MOSCS
- beq wait_pmc_sr_1
+ ldr r1, =AT91_PMC_SR_MOSCS
+ bl wait_for_flag_pcm_r0r1
// Set the PLL multiplier and divider. 16 slow clocks go by
// before the LOCK bit is set. */
- ldr r1,=((AT91_PMC_PLLR_DIV(CYGNUM_HAL_ARM_AT91_PLL_DIVIDER))|(AT91_PMC_PLLR_PLLCOUNT(CYGNUM_HAL_ARM_AT91_PLL_COUNT))|(AT91_PMC_PLLR_MUL(CYGNUM_HAL_ARM_AT91_PLL_MULTIPLIER-1)))
- str r1,[r0,#AT91_PMC_PLLR]
-
+ str r3,[r0,#AT91_PMC_PLLR]
// Wait for PLL locked indication
-wait_pmc_sr_2:
- ldr r1,[r0,#AT91_PMC_SR]
- ands r1,r1,#AT91_PMC_SR_LOCK
- beq wait_pmc_sr_2
+ ldr r1, =AT91_PMC_SR_LOCK
+ bl wait_for_flag_pcm_r0r1
// Enable the PLL clock and set the prescale to 2 */
- ldr r1,=(AT91_PMC_MCKR_PRES_CLK_2|AT91_PMC_MCKR_PLL_CLK)
- str r1,[r0,#AT91_PMC_MCKR]
-
+ str r4,[r0,#AT91_PMC_MCKR]
// Wait for the MCLK ready indication
-wait_pmc_sr_3:
- ldr r1,[r0,#AT91_PMC_SR]
- ands r1,r1,#AT91_PMC_SR_MCKRDY
- beq wait_pmc_sr_3
+ ldr r1, =AT91_PMC_SR_MCKRDY
+ bl wait_for_flag_pcm_r0r1
+
+pmc_done:
.endm
+
// Remap the flash from address 0x0 and place RAM there instead.
.macro _remap_flash
__remap_flash:
@@ -137,7 +167,7 @@
ldr r2,[r0] // Save away copies so we can restore them
ldr r3,[r1]
ldr r4,=0xffffff
- eor r4,r3,r4 // XOR the contents of 0x20004
+ eor r4,r3,r4 // XOR the contents of 0x20004
str r4,[r1] // and write it
ldr r5,[r0] // Read from low memory
cmp r5,r4
@@ -148,11 +178,16 @@
remap_done:
str r3,[r1] // restore the value we changed
.endm
-
-#if defined(CYG_HAL_STARTUP_ROM)
- .macro _setup
- _flash_init
+
+
+ .macro _setup //The "main" of the macros...
+ _subroutines
+ ldr sp,.__startup_stack
+ ldr r1,=AT91_PMC_FLASH_VALUE_SLOW // May be we run >60Mhz at the moment
+ bl set_flash_from_r1
_main_clock_init
+ ldr r1,=AT91_PMC_FLASH_VALUE
+ bl set_flash_from_r1
_remap_flash
.endm
Index: packages/hal/arm/at91/at91sam7s/current/include/plf_io.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/at91/at91sam7s/current/include/plf_io.h,v
retrieving revision 1.10
diff -u -r1.10 plf_io.h
--- packages/hal/arm/at91/at91sam7s/current/include/plf_io.h 3 Nov 2008 08:40:01 -0000 1.10
+++ packages/hal/arm/at91/at91sam7s/current/include/plf_io.h 4 Jun 2009 07:30:50 -0000
@@ -41,9 +41,9 @@
//
// Author(s): tkoeller
// Contributors: andrew lunn, Oliver Munz
-// Date: 2005-12-31
+// Date: 2009-06-03
// Purpose: Atmel AT91SAM7S board specific registers
-// Description:
+// Description:
// Usage: #include <cyg/hal/plf_io.h>
//
//####DESCRIPTIONEND####
@@ -62,7 +62,7 @@
#define AT91_SPI AT91_SPI0
-// DMA registers
+// DMA registers
#define AT91_SPI_RPR 0x100 // Receive Pointer Register
#define AT91_SPI_RCR 0x104 // Receive Counter Register
#define AT91_SPI_TPR 0x108 // Transmit Pointer Register
@@ -92,8 +92,8 @@
// Define USART2 to be the debug UART. It is similar enough to a USART
// that both the hal_diag and interrupt driven driver will work.
// However trying to change parity, start/stop bits etc will not work.
-#define CYGNUM_HAL_INTERRUPT_USART2 CYGNUM_HAL_INTERRUPT_DBG
-#define AT91_USART2 AT91_DBG
+#define CYGNUM_HAL_INTERRUPT_USART2 CYGNUM_HAL_INTERRUPT_DBG
+#define AT91_USART2 AT91_DBG
#ifndef __ASSEMBLER__
#ifdef CYGBLD_HAL_ARM_AT91_BAUD_DYNAMIC
@@ -108,7 +108,7 @@
#define AT91_US_TCR 0x10C // Transmit Counter Register
#define AT91_US_NRPR 0x110 // Next Receive Pointer Register
#define AT91_US_NRCR 0x114 // Next Receive Counter Register
-#define AT91_US_NTPR 0x118 // Next Transmit Pointer Register
+#define AT91_US_NTPR 0x118 // Next Transmit Pointer Register
#define AT91_US_NTCR 0x11C // Next Transmit Counter Register
#define AT91_US_PTCR 0x120 // PDC Transfer Control Register
#define AT91_US_PTSR 0x124 // PDC Transfer Status Register
@@ -175,16 +175,19 @@
// CAN - Controller Area Network
-#define AT91_CAN 0xFFFD0000
+#define AT91_CAN 0xFFFD0000
#endif
#if defined(CYGHWR_HAL_ARM_AT91SAM7_at91sam7x512) || \
defined(CYGHWR_HAL_ARM_AT91SAM7_at91sam7s512) || \
defined(CYGHWR_HAL_ARM_AT91SAM7_at91sam7se512)
-#define AT91_MC_FMR0 0x60
-#define AT91_MC_FMR1 0x70
-#define AT91_MC_FMR AT91_MC_FMR0
+#define AT91_MC_FMR0 AT91_MC_FMR
+#define AT91_MC_FCR0 AT91_MC_FCR
+#define AT91_MC_FSR0 AT91_MC_FSR
+#define AT91_MC_FMR1 (AT91_MC_FMR + 0x10)
+#define AT91_MC_FCR1 (AT91_MC_FCR + 0x10)
+#define AT91_MC_FSR1 (AT91_MC_FSR + 0x10)
#endif
//----------------------------------------------------------------------
@@ -199,9 +202,9 @@
extern void hal_plf_eth_init(void);
#define HAL_PLF_ETH_INIT() \
hal_plf_eth_init()
-#endif
+#endif
-#endif //__ASSEMBLER__
+#endif //__ASSEMBLER__
#endif //CYGONCE_HAL_PLF_IO_H
Index: packages/hal/arm/at91/var/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/at91/var/current/ChangeLog,v
retrieving revision 1.44
diff -u -r1.44 ChangeLog
--- packages/hal/arm/at91/var/current/ChangeLog 3 Nov 2008 08:39:26 -0000 1.44
+++ packages/hal/arm/at91/var/current/ChangeLog 4 Jun 2009 07:30:52 -0000
@@ -1,3 +1,9 @@
+2009-06-03 Oliver Munz oli@snr.ch
+ * Fix the a problem in the kernel delay_us, if the PIT is initalised
+ later then the periode. If the PIT has a big periode (after reset)
+ and has to be set to a lower periode one has to be sure that the counter
+ is lower then the periode value one want to set...
+
2008-11-03 Gabor Toeroek <tgabor84@gmail.com>
* include/var_io.h: Added defines for AT91SAM7SE.
Index: packages/hal/arm/at91/var/current/src/timer_pit.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/hal/arm/at91/var/current/src/timer_pit.c,v
retrieving revision 1.4
diff -u -r1.4 timer_pit.c
--- packages/hal/arm/at91/var/current/src/timer_pit.c 20 Feb 2007 21:33:03 -0000 1.4
+++ packages/hal/arm/at91/var/current/src/timer_pit.c 4 Jun 2009 07:30:52 -0000
@@ -39,9 +39,9 @@
//
// Author(s): asl, Oliver Munz
// Contributors: asl, Oliver Munz
-// Date: 2006-02-12
+// Date: 2009-06-03
// Purpose: Clock support using the PIT
-// Description:
+// Description:
//
//####DESCRIPTIONEND####
//
@@ -57,21 +57,48 @@
// -------------------------------------------------------------------------
// Use system clock
void
-hal_clock_initialize(cyg_uint32 period)
-{
- cyg_uint32 sr;
-
- CYG_ASSERT(CYGNUM_HAL_INTERRUPT_RTC == CYGNUM_HAL_INTERRUPT_PITC,
- "Invalid timer interrupt");
-
- /* Set Period Interval timer and enable interrupt */
- HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
- (period - 1) |
- AT91_PITC_PIMR_PITEN |
- AT91_PITC_PIMR_PITIEN);
-
- // Read the status register to clear any pending interrupt
- HAL_READ_UINT32(AT91_PITC + AT91_PITC_PISR, sr);
+hal_clock_initialize(cyg_uint32 period){
+
+ cyg_uint32 ir;
+ cyg_uint32 pimr;
+
+ CYG_ASSERT(CYGNUM_HAL_INTERRUPT_RTC == CYGNUM_HAL_INTERRUPT_PITC,
+ "Invalid timer interrupt");
+ CYG_ASSERT(period <= AT91_PITC_VALUE_MASK,
+ "Invalid timer period");
+
+ pimr = (period - 1); /* This is what we want */
+ HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIIR, ir); /* Counter */
+ ir = ir & AT91_PITC_VALUE_MASK; /* The current counts */
+
+ do { /* Test if the new PITC-Moduls is overrun by the counter */
+
+ if (ir > pimr){ /* If the counter is already to high */
+
+ pimr = (ir + 100) & AT91_PITC_VALUE_MASK; /* Set the comparator a head */
+ HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
+ pimr | AT91_PITC_PIMR_PITEN);
+ }
+ if (ir < (period - 1)){ /* If we can try it */
+
+ pimr = (period - 1); /* This is what we want */
+ /* Set the real Period Interval timer */
+ HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
+ pimr | AT91_PITC_PIMR_PITEN);
+ }
+ HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIMR, pimr); /* The real value */
+ pimr = pimr & AT91_PITC_VALUE_MASK; /* Value */
+ HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIIR, ir); /* Counter */
+ ir = ir & AT91_PITC_VALUE_MASK; /* The current counts */
+
+ } while (ir > (period -1) || pimr != (period - 1)); // Is it correct?
+
+ /* Enable interrupt */
+ HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR), (period - 1) |
+ AT91_PITC_PIMR_PITEN | AT91_PITC_PIMR_PITIEN);
+
+ /* Read the status register to clear any pending interrupt */
+ HAL_READ_UINT32(AT91_PITC + AT91_PITC_PISR, ir);
}
// This routine is called during a clock interrupt.
@@ -80,14 +107,14 @@
{
cyg_uint32 reg;
cyg_uint32 pimr;
-
+
CYG_ASSERT(period < AT91_PITC_VALUE_MASK, "Invalid HAL clock configuration");
-
+
// Check that the PIT has the right period.
HAL_READ_UINT32((AT91_PITC + AT91_PITC_PIMR), pimr);
if ((pimr & AT91_PITC_VALUE_MASK) != (period - 1)) {
- HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
- (period - 1) |
+ HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
+ (period - 1) |
AT91_PITC_PIMR_PITEN |
AT91_PITC_PIMR_PITIEN);
}
@@ -104,14 +131,14 @@
{
cyg_uint32 ir;
cyg_uint32 pimr;
-
+
// Check that the PIT is running. If not start it.
HAL_READ_UINT32((AT91_PITC + AT91_PITC_PIMR),pimr);
if (!(pimr & AT91_PITC_PIMR_PITEN)) {
- HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
+ HAL_WRITE_UINT32((AT91_PITC + AT91_PITC_PIMR),
AT91_PITC_VALUE_MASK | AT91_PITC_PIMR_PITEN);
}
-
+
HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIIR, ir);
*pvalue = ir & AT91_PITC_VALUE_MASK;
}
@@ -126,23 +153,23 @@
cyg_int64 ticks;
cyg_uint32 val1, val2;
cyg_uint32 piv;
-
+
// Calculate how many PIT ticks the required number of microseconds
// equate to. We do this calculation in 64 bit arithmetic to avoid
// overflow.
- ticks = (((cyg_uint64)usecs) *
+ ticks = (((cyg_uint64)usecs) *
((cyg_uint64)CYGNUM_HAL_ARM_AT91_CLOCK_SPEED))/16/1000000LL;
-
- // Calculate the wrap around period.
+
+ // Calculate the wrap around period.
HAL_READ_UINT32(AT91_PITC + AT91_PITC_PIMR, piv);
- piv = (piv & AT91_PITC_VALUE_MASK) - 1;
-
+ piv = (piv & AT91_PITC_VALUE_MASK) - 1;
+
hal_clock_read(&val1);
while (ticks > 0) {
hal_clock_read(&val2);
if (val2 < val1)
ticks -= ((piv + val2) - val1); //overflow occurred
- else
+ else
ticks -= (val2 - val1);
val1 = val2;
}