Merged nuttx/nuttx into master

This commit is contained in:
Aleksandr Vyhovanec
2016-12-08 11:41:11 +03:00
809 changed files with 17479 additions and 20581 deletions
-28
View File
@@ -4920,34 +4920,6 @@ Mem: 29232 5920 23312 23312
</ul>
</td>
</tr>
<tr>
<td><br></td>
<td><hr></td>
</tr>
<tr>
<td><br></td>
<td>
<p>
<b>RGMP</b>.
RGMP stands for RTOS and GPOS on Multi-Processor.
RGMP is a project for running GPOS and RTOS simultaneously on multi-processor platforms
You can port your favorite RTOS to RGMP together with an unmodified Linux to form a hybrid operating system.
This makes your application able to use both RTOS and GPOS features.
</p>
<p>
See the <a href="http://rgmp.sourceforge.net/wiki/index.php/Main_Page">RGMP Wiki</a> for further information about RGMP.
</p>
<ul>
<p>
<b>STATUS:</b>
This initial port of NuttX to RGMP was provided in NuttX-6.3.
This initial RGP port provides only minimal driver support and does not use the native NuttX interrupt system.
This is a great, stable starting point for anyone interest in working with NuttX under RGMP!
Refer to the NuttX <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/rgmp/README.txt" target="_blank">README</a> file for further information.
</p>
</ul>
</td>
</tr>
<tr>
<td valign="top"><img height="20" width="20" src="favicon.ico"></td>
<td bgcolor="#5eaee1">
+3 -3
View File
@@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX README Files</i></font></big></h1>
<p>Last Updated: November 14, 2016</p>
<p>Last Updated: December 4, 2016</p>
</td>
</tr>
</table>
@@ -203,8 +203,6 @@ nuttx/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/pirelli_dpl10/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- qemu-i486/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/qemu-i486/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- rgmp/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/rgmp/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- sabre-6quad/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/sabre-6quad/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- sama5d2-xult/
@@ -223,6 +221,8 @@ nuttx/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/saml21-xplained/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- sam3u-ek/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/sam3u-ek/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- sam4cmp-db
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/sam4cmp-d/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- sam4e-ek/
| | `- <a href="https://bitbucket.org/nuttx/nuttx/src/master/configs/sam4e-ek/README.txt" target="_blank"><b><i>README.txt</i></b></a>
| |- sam4l-xplained/
+2 -2
View File
@@ -1419,8 +1419,6 @@ nuttx/
| | `- README.txt
| |- qemu-i486/
| | `- README.txt
| |- rgmp/
| | `- README.txt
| |- sabre-6quad/
| | `- README.txt
| |- sama5d2-xult/
@@ -1439,6 +1437,8 @@ nuttx/
| | `- README.txt
| |- sam3u-ek/
| | `- README.txt
| |- sam4cmp-db
| | `- README.txt
| |- sam4e-ek/
| | `- README.txt
| |- sam4l-xplained/
+33 -56
View File
@@ -1,4 +1,4 @@
NuttX TODO List (Last updated November 22, 2016)
NuttX TODO List (Last updated December 3, 2016)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This file summarizes known NuttX bugs, limitations, inconsistencies with
@@ -308,33 +308,33 @@ o Task/Scheduler (sched/)
o SMP
^^^
Title: SPINLOCKS AND DATA CACHES
Description: If spinlocks are used in a system with a data cache, then there
may be a problem with cache coherency in some CPU architectures:
When one CPU modifies the spinlock, the changes may not be
visible to another CPU if it does not share the data cache.
That would cause failure in the spinlock logic.
Title: SMP AND DATA CACHES
Description: When spinlocks, semaphores, etc. are used in an SMP system with
a data cache, then there may be problems with cache coherency
in some CPU architectures: When one CPU modifies the shared
object, the changes may not be visible to another CPU if it
does not share the data cache. That would cause failure in
the IPC logic.
Flushing the D-cache on writes and invalidating before a read is
not really an option. spinlocks are normally 8-bits in size and
cache lines are typically 32-bytes so that would have side effects
unless the spinlocks were made to be the same size as one cache
line.
not really an option. That would essentially effect every memory
access and there may be side-effects due to cache line sizes
and alignment.
This might be doable if a write-through cache is used. Then you
could always safely invalidate the cache line before reading the
spinlock because there should never be any dirty cache lines in
this case.
For the same reason a separate, non-cacheable memory region is
not an option. Essentially all data would have to go in the
non-cached region and you would have no benefit from the data
cache.
The better option is to add compiler independent "ornamentation"
to the spinlock so that the spinlocks are all linked together
into a separate, non-cacheable memory regions. Because of
region alignment and minimum region mapping sizes this could
still be wasteful of memory. This would work in systems that
have both data cache and either an MPU or an MMU.
Status: Open
Priority: High. spinlocks, and hence SMP, will not work on such systems
without this change.
On ARM Cortex-A, each CPU has a separate data cache. However,
the MPCore's Snoop Controller Unit supports coherency among
the different caches. The SCU is enabled by the SCU control
register and each CPU participates in the SMP coherency by
setting the ACTLR_SMP bit in the auxiliary control register
(ACTLR).
Status: Closed
Priority: High on platforms that may have the issue.
o Memory Management (mm/)
^^^^^^^^^^^^^^^^^^^^^^^
@@ -1043,41 +1043,18 @@ o Network (net/, drivers/net)
Priority: Medium. Important on slow applications that will not accept
connections promptly.
Title: INTERRUPT LEVEL PROCESSING IN ETHERNET DRIVERS
Description: Too many Ethernet drivers do interrupt-level processing with
the network stack. The network stack supports either interrupt
level processing or normal task level processing (depending on
CONFIG_NET_NOINTS). This is really a very bad use of CPU
resources; All of the network stack processing should be
modified to use a work queue (and, all use of CONFIG_NET_NOINTS=n
should be eliminated). This applies to many Ethernet drivers:
Title: IPv6 REQUIRES ADDRESS FILTER SUPPORT
Description: IPv6 requires that the Ethernet driver support NuttX address
filter interfaces. Several Ethernet drivers do support there,
however. Others support the address filtering interfaces but
have never been verifed:
ARCHITECTURE CONFIG_NET_NOINTS? ADDRESS FILTER SUPPORT?
C5471 NO NO
STM32 YES YES
STM32F7 YES YES
TIVA ----------------------- ------
LM3S NO NO
TM4C YES YES
eZ80 NO NO
Kinetis YES YES (not tested)
LPC17xx YES YES (not tested)
LPC43xx YES YES (not tested)
DMxxx NIC NO NO
PIC32 NO NO
RGMP ??? ???
SAM3/4 YES YES
SAMA5D ----------------------- ------
EMACA NO YES (not tested)
EMACB YES YES
GMAC NO YES (not tested)
SAMV7 YES YES
SIM N/A (No interrupts) NO
C5471, LM3X, ez80, DM0x90 NIC, PIC: Do not support address
filteringing.
Kinetis, LPC17xx, LPC43xx: Untested address filter support
The general outline of how this might be done is included in
drivers/net/skeleton.c
Status: Open
Priority: Pretty high if you want a well behaved system.
Priority: Pretty high if you want a to use IPv6 on these platforms.
Title: UDP MULTICAST RECEPTION
Description: The logic in udp_input() expects either a single receive socket or
-8
View File
@@ -46,12 +46,6 @@ config ARCH_MISOC
---help---
MISOC
config ARCH_RGMP
bool "RGMP"
---help---
RTOS and GPOS on Multi-Processor (RGMP) architecture. See
http://rgmp.sourceforge.net/wiki/index.php/Main_Page.
config ARCH_RENESAS
bool "Renesas"
select ARCH_NOINTC
@@ -107,7 +101,6 @@ config ARCH
default "hc" if ARCH_HC
default "mips" if ARCH_MIPS
default "misoc" if ARCH_MISOC
default "rgmp" if ARCH_RGMP
default "renesas" if ARCH_RENESAS
default "risc-v" if ARCH_RISCV
default "sim" if ARCH_SIM
@@ -121,7 +114,6 @@ source arch/avr/Kconfig
source arch/hc/Kconfig
source arch/mips/Kconfig
source arch/misoc/Kconfig
source arch/rgmp/Kconfig
source arch/renesas/Kconfig
source arch/risc-v/Kconfig
source arch/sim/Kconfig
-11
View File
@@ -222,17 +222,6 @@ arch/renesas - Support for Renesas and legacy Hitachi microcontrollers.
arch/renesas/include/m16c and arch/renesas/src/m16c
arch/renesas/include/sh1 and arch/renesas/src/sh1
arch/rgmp
RGMP stands for RTOS and GPOS on Multi-Processor. RGMP is a project
for running GPOS and RTOS simultaneously on multi-processor platforms.
You can port your favorite RTOS to RGMP together with an unmodified
Linux to form a hybrid operating system. This makes your application
able to use both RTOS and GPOS features.
See http://rgmp.sourceforge.net/wiki/index.php/Main_Page for further
information about RGMP.
arch/risc-v
This directory is dedicated to ports to the RISC-V family.
@@ -1,12 +1,8 @@
/****************************************************************************
* arch/rgmp/src/arm/sigentry.S
* arch/arm/include/armv7-a/spinlock.h
*
* Copyright (C) 2011 Yu Qiang. All rights reserved.
* Author: Yu Qiang <yuq825@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,13 +33,7 @@
*
****************************************************************************/
.globl up_sigentry
up_sigentry:
sub sp, sp, #68 @ 68 is the size of Trapframe
mov r0, sp
bl up_sigdeliver
add sp, sp, #4 @ skip current_task
pop {r0-r12, lr}
rfefd sp!
#ifndef __ARCH_ARM_INCLUDE_ARM_SPINLOCK_H
#define __ARCH_ARM_INCLUDE_ARM_SPINLOCK_H
#endif /* __ARCH_ARM_INCLUDE_ARM_SPINLOCK_H */
@@ -1,12 +1,8 @@
/****************************************************************************
* arch/rgmp/include/arm/arch/subarch/arch.h
* arch/arm/include/armv7-a/spinlock.h
*
* Copyright (C) 2011 Yu Qiang. All rights reserved.
* Author: Yu Qiang <yuq825@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,22 +33,7 @@
*
****************************************************************************/
#ifndef __RGMP_ARCH_SUBARCH_ARCH_H
#define __RGMP_ARCH_SUBARCH_ARCH_H
#ifndef __ARCH_ARM_INCLUDE_ARMV6_M_SPINLOCK_H
#define __ARCH_ARM_INCLUDE_ARMV6_M_SPINLOCK_H
#ifndef __ASSEMBLY__
static inline void up_mdelay(uint32_t msec)
{
}
static inline void up_udelay(uint32_t usec)
{
}
#endif /* !__ASSEMBLY__ */
#endif
#endif /* __ARCH_ARM_INCLUDE_ARMV6_M_SPINLOCK_H */
@@ -1,12 +1,8 @@
/****************************************************************************
* arch/rgmp/include/x86/arch/subarch/arch.h
* arch/arm/include/armv7-a/spinlock.h
*
* Copyright (C) 2011 Yu Qiang. All rights reserved.
* Author: Yu Qiang <yuq825@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,32 +33,28 @@
*
****************************************************************************/
#ifndef __RGMP_ARCH_SUBARCH_ARCH_H
#define __RGMP_ARCH_SUBARCH_ARCH_H
#ifndef __ARCH_ARM_INCLUDE_ARMV7_A_SPINLOCK_H
#define __ARCH_ARM_INCLUDE_ARMV7_A_SPINLOCK_H
#ifndef __ASSEMBLY__
/****************************************************************************
* Included Files
****************************************************************************/
#ifdef __cplusplus
extern "C"
{
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Not a useful feature */
#undef SMP_INTERCPU_NONCACHED
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* In SMP configurations, save spinlocks and other inter-CPU communications
* data in a non-cached memory region.
*/
# define SP_SECTION __attribute__((section(".nocache")))
#endif
#include <rgmp/arch/hpet.h>
static inline void up_mdelay(uint32_t msec)
{
hpet_ndelay(msec*1000000);
}
static inline void up_udelay(uint32_t usec)
{
hpet_ndelay(usec*1000);
}
#ifdef __cplusplus
}
#endif
#endif /* !__ASSEMBLY__ */
#endif
#endif /* __ARCH_ARM_INCLUDE_ARMV7_A_SPINLOCK_H */
@@ -1,8 +1,8 @@
/****************************************************************************
* configs/misoc/include/generated/common.h
* arch/arm/include/armv7-a/spinlock.h
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Ramtin Amin <keytwo@gmail.com>
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -33,17 +33,7 @@
*
****************************************************************************/
#ifndef __CONFIGS_MISOC_INCLUDE_GENERATED_COMMON_H
#define __CONFIGS_MISOC_INCLUDE_GENERATED_COMMON_H
#ifndef __ARCH_ARM_INCLUDE_ARMV7_M_SPINLOCK_H
#define __ARCH_ARM_INCLUDE_ARMV7_M_SPINLOCK_H
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef __ASSEMBLER__
# define MMPTR(x) x
#else
# define MMPTR(x) (*((volatile unsigned int *)(x)))
#endif
#endif /* __CONFIGS_MISOC_INCLUDE_GENERATED_COMMON_H */
#endif /* __ARCH_ARM_INCLUDE_ARMV7_M_SPINLOCK_H */
@@ -1,12 +1,8 @@
/****************************************************************************
* arch/rgmp/src/x86/sigentry.S
* arch/arm/include/armv7-r/spinlock.h
*
* Copyright (C) 2011 Yu Qiang. All rights reserved.
* Author: Yu Qiang <yuq825@gmail.com>
*
* This file is a part of NuttX:
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -37,19 +33,7 @@
*
****************************************************************************/
.globl up_sigentry
up_sigentry:
subl $172, %esp # 172 is the size of Trapframe without cross ring part
pushl %esp
movl %esp, %eax
call up_sigdeliver
addl $8, %esp # skip parameter and tf_curregs
frstor 0(%esp)
addl $108, %esp
popal
popl %es
popl %ds
addl $0x8, %esp # trapno and errcode
iret
#ifndef __ARCH_ARM_INCLUDE_ARMV7_R_SPINLOCK_H
#define __ARCH_ARM_INCLUDE_ARMV7_R_SPINLOCK_H
#endif /* __ARCH_ARM_INCLUDE_ARMV7_R_SPINLOCK_H */
+20
View File
@@ -44,6 +44,26 @@
# include <stdint.h>
#endif /* __ASSEMBLY__ */
/* Include ARM architecture-specific IRQ definitions (including register
* save structure and up_irq_save()/up_irq_restore() functions)
*/
#if defined(CONFIG_ARCH_CORTEXA5) || defined(CONFIG_ARCH_CORTEXA8) || \
defined(CONFIG_ARCH_CORTEXA9)
# include <arch/armv7-a/spinlock.h>
#elif defined(CONFIG_ARCH_CORTEXR4) || defined(CONFIG_ARCH_CORTEXR4F) || \
defined(CONFIG_ARCH_CORTEXR5) || defined(CONFIG_ARCH_CORTEXR5F) || \
defined(CONFIG_ARCH_CORTEXR7) || defined(CONFIG_ARCH_CORTEXR7F)
# include <arch/armv7-r/spinlock.h>
#elif defined(CONFIG_ARCH_CORTEXM3) || defined(CONFIG_ARCH_CORTEXM4) || \
defined(CONFIG_ARCH_CORTEXM7)
# include <arch/armv7-m/spinlock.h>
#elif defined(CONFIG_ARCH_CORTEXM0)
# include <arch/armv6-m/spinlock.h>
#else
# include <arch/arm/spinlock.h>
#endif
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
+1 -1
View File
@@ -77,7 +77,7 @@
# define STM32L4_NBTIM 2 /* Two basic timers, TIM6-7 */
# define STM32L4_NLPTIM 2 /* Two low-power timers, LPTIM1-2 */
# define STM32L4_NRNG 1 /* Random number generator (RNG) */
# define STM32L4_NUART 4 /* UART 4-5 */
# define STM32L4_NUART 2 /* UART 4-5 */
# define STM32L4_NUSART 3 /* USART 1-3 */
# define STM32L4_NLPUART 1 /* LPUART 1 */
# define STM32L4_NSPI 3 /* SPI1-3 */
+5 -1
View File
@@ -308,7 +308,11 @@ __cpu3_start:
orr r0, r0, #(SCTLR_RR)
#endif
#ifndef CPU_DCACHE_DISABLE
/* In SMP configurations, the data cache will not be enabled until later
* after SMP cache coherency has been setup.
*/
#if 0 /* !defined(CPU_DCACHE_DISABLE) && !defined(CONFIG_SMP) */
/* Dcache enable
*
* SCTLR_C Bit 2: DCache enable
+37 -5
View File
@@ -44,6 +44,7 @@
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/spinlock.h>
#include <nuttx/sched_note.h>
#include "up_internal.h"
#include "gic.h"
@@ -69,8 +70,8 @@
* so that it will be ready for the next pause operation.
*/
static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS];
static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS];
static volatile spinlock_t g_cpu_wait[CONFIG_SMP_NCPUS] SP_SECTION;
static volatile spinlock_t g_cpu_paused[CONFIG_SMP_NCPUS] SP_SECTION;
/****************************************************************************
* Public Functions
@@ -131,23 +132,42 @@ int up_cpu_paused(int cpu)
sched_suspend_scheduler(tcb);
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify that we are paused */
sched_note_cpu_paused(tcb);
#endif
/* Save the current context at CURRENT_REGS into the TCB at the head
* of the assigned task list for this CPU.
*/
up_savestate(tcb->xcp.regs);
/* Wait for the spinlock to be released */
/* Release the g_cpu_puased spinlock to synchronize with the
* requesting CPU.
*/
spin_unlock(&g_cpu_paused[cpu]);
/* Wait for the spinlock to be released. The requesting CPU will release
* the spinlcok when the CPU is resumed.
*/
spin_lock(&g_cpu_wait[cpu]);
/* Restore the exception context of the tcb at the (new) head of the
* assigned task list.
/* This CPU has been resumed. Restore the exception context of the TCB at
* the (new) head of the assigned task list.
*/
tcb = this_task();
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify that we have resumed */
sched_note_cpu_resumed(tcb);
#endif
/* Reset scheduler parameters */
sched_resume_scheduler(tcb);
@@ -224,6 +244,12 @@ int up_cpu_pause(int cpu)
{
int ret;
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify of the pause event */
sched_note_cpu_pause(this_task(), cpu);
#endif
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
/* Take the both spinlocks. The g_cpu_wait spinlock will prevent the SGI2
@@ -287,6 +313,12 @@ int up_cpu_pause(int cpu)
int up_cpu_resume(int cpu)
{
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify of the resume event */
sched_note_cpu_resume(this_task(), cpu);
#endif
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
/* Release the spinlock. Releasing the spinlock will cause the SGI2
+16 -4
View File
@@ -43,10 +43,11 @@
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/sched_note.h>
#include "up_internal.h"
#include "gic.h"
#include "cp15_cacheops.h"
#include "gic.h"
#include "sched/sched.h"
#ifdef CONFIG_SMP
@@ -104,13 +105,18 @@ static inline void arm_registerdump(FAR struct tcb_s *tcb)
int arm_start_handler(int irq, FAR void *context)
{
FAR struct tcb_s *tcb;
FAR struct tcb_s *tcb = this_task();
sinfo("CPU%d Started\n", up_cpu_index());
sinfo("CPU%d Started\n", this_cpu());
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify that this CPU has started */
sched_note_cpu_started(tcb);
#endif
/* Reset scheduler parameters */
tcb = this_task();
sched_resume_scheduler(tcb);
/* Dump registers so that we can see what is going to happen on return */
@@ -159,6 +165,12 @@ int up_cpu_start(int cpu)
DEBUGASSERT(cpu >= 0 && cpu < CONFIG_SMP_NCPUS && cpu != this_cpu());
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Notify of the start event */
sched_note_cpu_start(this_task(), cpu);
#endif
/* Make the content of CPU0 L1 cache has been written to coherent L2 */
cp15_clean_dcache(CONFIG_RAM_START, CONFIG_RAM_END - 1);
+153 -11
View File
@@ -40,10 +40,10 @@
#include <nuttx/config.h>
#include <stdint.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <assert.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/board.h>
#include <arch/board/board.h>
@@ -51,21 +51,40 @@
#include "up_internal.h"
#include "group/group.h"
#include "gic.h"
/****************************************************************************
* Private Data
****************************************************************************/
/* A bit set of pending, non-maskable SGI interrupts, on bit set for each
* supported CPU.
*/
#ifdef CONFIG_ARMV7A_HAVE_GICv2
#ifdef CONFIG_SMP
static uint16_t g_sgi_pending[CONFIG_SMP_NCPUS];
#else
static uint16_t g_sgi_pending[1];
#endif
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
uint32_t *arm_doirq(int irq, uint32_t *regs)
/****************************************************************************
* Name: _arm_doirq
*
* Description:
* Receives the one decoded interrupt and dispatches control to the
* attached interrupt handler.
*
****************************************************************************/
#ifndef CONFIG_SUPPRESS_INTERRUPTS
static inline uint32_t *_arm_doirq(int irq, uint32_t *regs)
{
board_autoled_on(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
PANIC();
#else
/* Nested interrupts are not supported */
DEBUGASSERT(CURRENT_REGS == NULL);
/* Current regs non-zero indicates that we are processing an interrupt;
* CURRENT_REGS is also used to manage interrupt level context switches.
*/
@@ -110,8 +129,131 @@ uint32_t *arm_doirq(int irq, uint32_t *regs)
regs = (uint32_t *)CURRENT_REGS;
CURRENT_REGS = NULL;
return regs;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: arm_doirq
*
* Description:
* Receives the decoded GIC interrupt information and dispatches control
* to the attached interrupt handler. There are two versions:
*
* 1) For the simple case where all interrupts are maskable. In that
* simple case, arm_doirq() is simply a wrapper for the inlined
* _arm_do_irq() that does the real work.
*
* 2) With the GICv2, there are 16 non-maskable software generated
* interrupts (SGIs) that also come through arm_doirq(). In that case,
* we must avoid nesting interrupt handling and serial the processing.
*
****************************************************************************/
#ifndef CONFIG_ARMV7A_HAVE_GICv2
uint32_t *arm_doirq(int irq, uint32_t *regs)
{
board_autoled_on(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
PANIC();
#else
/* Nested interrupts are not supported */
DEBUGASSERT(CURRENT_REGS == NULL);
/* Dispatch the interrupt to its attached handler */
regs = _arm_doirq(irq, regs);
#endif
board_autoled_off(LED_INIRQ);
return regs;
}
#endif
#ifdef CONFIG_ARMV7A_HAVE_GICv2
uint32_t *arm_doirq(int irq, uint32_t *regs)
{
#ifndef CONFIG_SUPPRESS_INTERRUPTS
uint32_t bit;
int cpu;
int i;
#endif
board_autoled_on(LED_INIRQ);
#ifdef CONFIG_SUPPRESS_INTERRUPTS
PANIC();
#else
/* Get the CPU processing the interrupt */
#ifdef CONFIG_SMP
cpu = up_cpu_index();
#else
cpu = 0;
#endif
/* Non-zero CURRENT_REGS indicates that we are already processing an
* interrupt. This could be a normal event for the case of the GICv2;
* Software generated interrupts are non-maskable.
*
* REVISIT: There is no support for nested SGIs! That will cause an
* assertion below. There is also no protection for concurrent access
* to g_sgi_pending for that case.
*/
if (CURRENT_REGS != NULL)
{
int ndx = irq - GIC_IRQ_SGI0;
bit = (1 << (ndx));
/* Only an SGI should cause this event. We also cannot support
* multiple pending SGI interrupts.
*/
ASSERT((unsigned int)irq <= GIC_IRQ_SGI15 &&
(g_sgi_pending[cpu] & bit) == 0);
/* Mare the SGI as pending and return immediately */
sinfo("SGI%d pending\n", ndx);
g_sgi_pending[cpu] |= bit;
return regs;
}
/* Dispatch the interrupt to its attached handler */
regs = _arm_doirq(irq, regs);
/* Then loop dispatching any pending SGI interrupts that occcurred during
* processing of the interrupts.
*/
for (i = 0; i < 16 && g_sgi_pending[cpu] != 0; i++)
{
/* Check if this SGI is pending */
bit = (1 << i);
if ((g_sgi_pending[cpu] & bit) != 0)
{
/* Clear the pending bit */
g_sgi_pending[cpu] &= ~bit;
/* And dispatch the SGI */
sinfo("Dispatching pending SGI%d\n", i + GIC_IRQ_SGI0);
regs = _arm_doirq(i + GIC_IRQ_SGI0, regs);
}
}
#endif
board_autoled_off(LED_INIRQ);
return regs;
}
#endif
+1 -2
View File
@@ -122,7 +122,7 @@ void arm_gic0_initialize(void)
}
#ifdef CONFIG_SMP
/* Attach SGI interrupt handlers */
/* Attach SGI interrupt handlers. This attaches the handler for all CPUs. */
DEBUGVERIFY(irq_attach(GIC_IRQ_SGI1, arm_start_handler));
DEBUGVERIFY(irq_attach(GIC_IRQ_SGI2, arm_pause_handler));
@@ -574,5 +574,4 @@ int arm_gic_irq_trigger(int irq, bool edge)
return -EINVAL;
}
#endif /* CONFIG_ARMV7A_HAVE_GICv2 */
+6 -2
View File
@@ -450,7 +450,11 @@ __start:
orr r0, r0, #(SCTLR_RR)
#endif
#ifndef CPU_DCACHE_DISABLE
/* In SMP configurations, the data cache will not be enabled until later
* after SMP cache coherency has been setup.
*/
#if !defined(CPU_DCACHE_DISABLE) && !defined(CONFIG_SMP)
/* Dcache enable
*
* SCTLR_C Bit 2: DCache enable
@@ -638,7 +642,7 @@ __start:
#endif
/* Perform early C-level, platform-specific initialization. Logic
* within arm_boot() must configure SDRAM and call arm_ram_initailize.
* within arm_boot() must configure SDRAM and call arm_data_initialize().
*/
bl arm_boot
+6 -2
View File
@@ -434,7 +434,11 @@ __start:
orr r0, r0, #(SCTLR_RR)
#endif
#ifndef CPU_DCACHE_DISABLE
/* In SMP configurations, the data cache will not be enabled until later
* after SMP cache coherency has been setup.
*/
#if !defined(CPU_DCACHE_DISABLE) && !defined(CONFIG_SMP)
/* Dcache enable
*
* SCTLR_C Bit 2: DCache enable
@@ -670,7 +674,7 @@ __start:
#endif
/* Perform early C-level, platform-specific initialization. Logic
* within arm_boot() must configure SDRAM and call arm_ram_initailize.
* within arm_boot() must configure SDRAM and call arm_data_initialize().
*/
bl arm_boot
+227
View File
@@ -0,0 +1,227 @@
/****************************************************************************
* arch/arm/src/armv7-a/arm_scu.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include "up_arch.h"
#include "cp15_cacheops.h"
#include "sctlr.h"
#include "cache.h"
#include "scu.h"
#ifdef CONFIG_SMP
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: arm_get_sctlr
*
* Description:
* Get the contents of the SCTLR register
*
****************************************************************************/
static inline uint32_t arm_get_sctlr(void)
{
uint32_t sctlr;
__asm__ __volatile__
(
"\tmrc p15, 0, %0, c1, c0, 0\n" /* Read SCTLR */
: "=r"(sctlr)
:
:
);
return sctlr;
}
/****************************************************************************
* Name: arm_set_sctlr
*
* Description:
* Set the contents of the SCTLR register
*
****************************************************************************/
static inline void arm_set_sctlr(uint32_t sctlr)
{
__asm__ __volatile__
(
"\tmcr p15, 0, %0, c1, c0, 0\n" /* Write SCTLR */
:
: "r"(sctlr)
:
);
}
/****************************************************************************
* Name: arm_get_actlr
*
* Description:
* Get the contents of the ACTLR register
*
****************************************************************************/
static inline uint32_t arm_get_actlr(void)
{
uint32_t actlr;
__asm__ __volatile__
(
"\tmrc p15, 0, %0, c1, c0, 1\n" /* Read ACTLR */
: "=r"(actlr)
:
:
);
return actlr;
}
/****************************************************************************
* Name: arm_set_actlr
*
* Description:
* Set the contents of the ACTLR register
*
****************************************************************************/
static inline void arm_set_actlr(uint32_t actlr)
{
__asm__ __volatile__
(
"\tmcr p15, 0, %0, c1, c0, 1\n" /* Write ACTLR */
:
: "r"(actlr)
:
);
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: arm_enable_smp
*
* Description:
* Enable the SCU and make certain that current CPU is participating in
* the SMP cache coherency.
*
* Assumption:
* Called early in the CPU start-up. No special critical sections are
* needed if only CPU-private registers are modified.
*
****************************************************************************/
void arm_enable_smp(int cpu)
{
uint32_t regval;
/* Handle actions unique to CPU0 which comes up first */
if (cpu == 0)
{
/* Invalidate the SCU duplicate tags for all processors */
putreg32((SCU_INVALIDATE_ALL_WAYS << SCU_INVALIDATE_CPU0_SHIFT) |
(SCU_INVALIDATE_ALL_WAYS << SCU_INVALIDATE_CPU1_SHIFT) |
(SCU_INVALIDATE_ALL_WAYS << SCU_INVALIDATE_CPU2_SHIFT) |
(SCU_INVALIDATE_ALL_WAYS << SCU_INVALIDATE_CPU3_SHIFT),
SCU_INVALIDATE);
/* Invalidate CPUn L1 data cache so that is will we be reloaded from
* coherent L2.
*/
cp15_invalidate_dcache_all();
ARM_DSB();
/* Invalidate the L2C-310 -- Missing logic. */
/* Enable the SCU */
regval = getreg32(SCU_CTRL);
regval |= SCU_CTRL_ENABLE;
putreg32(regval, SCU_CTRL);
}
/* Actions for other CPUs */
else
{
/* Invalidate CPUn L1 data cache so that is will we be reloaded from
* coherent L2.
*/
cp15_invalidate_dcache_all();
ARM_DSB();
/* Wait for the SCU to be enabled by the primary processor -- should
* not be necessary.
*/
}
/* Enable the data cache, set the SMP mode with ACTLR.SMP=1.
*
* SMP - Sgnals if the Cortex-A9 processor is taking part in coherency
* or not.
*
* Cortex-A9 also needs ACTLR.FW=1
*
* FW - Cache and TLB maintenance broadcast.
*/
regval = arm_get_actlr();
regval |= ACTLR_SMP;
#ifdef CONFIG_ARCH_CORTEXA9
regval |= ACTLR_FW;
#endif
arm_set_actlr(regval);
regval = arm_get_sctlr();
regval |= SCTLR_C;
arm_set_sctlr(regval);
}
#endif
+10
View File
@@ -50,6 +50,16 @@
* Pre-processor Definitions
************************************************************************************/
/* Intrinsics are used in these inline functions */
#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory")
#define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory")
#define arm_dmb(n) __asm__ __volatile__ ("dmb " #n : : : "memory")
#define ARM_DSB() arm_dsb(15)
#define ARM_ISB() arm_isb(15)
#define ARM_DMB() arm_dmb(15)
/************************************************************************************
* Inline Functions
************************************************************************************/
+25 -1
View File
@@ -601,11 +601,13 @@
#define MMU_L2_PGTABFLAGS (PTE_TYPE_SMALL | PTE_WRITE_THROUGH | PTE_AP_RW1)
#define MMU_L1_VECTORFLAGS (PMD_TYPE_PTE | PMD_PTE_PXN | PMD_PTE_DOM(0))
#define MMU_L2_VECTRWFLAGS (PTE_TYPE_SMALL | PTE_WRITE_THROUGH | PTE_AP_RW1)
#define MMU_L2_VECTROFLAGS (PTE_TYPE_SMALL | PTE_WRITE_THROUGH | PTE_AP_R1)
#define MMU_L2_VECTORFLAGS MMU_L2_VECTRWFLAGS
#define MMU_L1_INTERCPUFLAGS (PMD_TYPE_PTE | PMD_PTE_PXN | PMD_PTE_DOM(0))
#define MMU_L2_INTERCPUFLAGS (PTE_TYPE_SMALL | PTE_DEVICE | PTE_AP_RW1)
/* Mapped section size */
#define SECTION_SHIFT (20)
@@ -1423,6 +1425,28 @@ void mmu_l1_restore(uintptr_t vaddr, uint32_t l1entry);
# define mmu_l1_clrentry(v) mmu_l1_restore(v,0)
#endif
/****************************************************************************
* Name: mmu_l2_setentry
*
* Description:
* Set one small (4096B) entry in a level2 translation table.
*
* Input Parameters:
* l2vaddr - the virtual address of the beginning of the L2 translation
* table.
* paddr - The physical address to be mapped. Must be aligned to a 4KB
* address boundary
* vaddr - The virtual address to be mapped. Must be aligned to a 4KB
* address boundary
* mmuflags - The MMU flags to use in the mapping.
*
****************************************************************************/
#ifndef CONFIG_ARCH_ROMPGTABLE
void mmu_l2_setentry(uint32_t l2vaddr, uint32_t paddr, uint32_t vaddr,
uint32_t mmuflags);
#endif
/************************************************************************************
* Name: mmu_l1_map_region
*
+176
View File
@@ -0,0 +1,176 @@
/****************************************************************************
* arch/arm/src/armv7-a/scu.h
* Generic Interrupt Controller Definitions
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Reference:
* Cortex-A9 MPCore, Revision: r4p1, Technical Reference Manual, ARM DDI
* 0407I (ID091612).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __ARCH_ARM_SRC_ARMV7_A_SCU_H
#define __ARCH_ARM_SRC_ARMV7_A_SCU_H
/****************************************************************************
* Included Files
****************************************************************************/
#include "mpcore.h" /* For MPCORE_SCU_VBASE */
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Register offsets *********************************************************/
#define SCU_CTRL_OFFSET 0x0000 /* SCU Control Register (Implementation defined) */
#define SCU_CONFIG_OFFSET 0x0004 /* SCU Configuration Register (Implementation defined) */
#define SCU_PWRSTATUS_OFFSET 0x0008 /* SCU CPU Power Status Register */
#define SCU_INVALIDATE_OFFSET 0x000c /* SCU Invalidate All Registers in Secure State */
#define SCU_FILTERSTART_OFFSET 0x0040 /* Filtering Start Address Register Defined by FILTERSTART input */
#define SCU_FILTEREND_OFFSET 0x0044 /* Filtering End Address Register Defined by FILTEREND input */
#define SCU_SAC_OFFSET 0x0050 /* SCU Access Control (SAC) Register */
#define SCU_SNSAC_OFFSET 0x0054 /* SCU Non-secure Access Control (SNSAC) Register */
/* Register addresses *******************************************************/
#define SCU_CTRL (MPCORE_SCU_VBASE+SCU_CTRL_OFFSET)
#define SCU_CONFIG (MPCORE_SCU_VBASE+SCU_CONFIG_OFFSET)
#define SCU_PWRSTATUS (MPCORE_SCU_VBASE+SCU_PWRSTATUS_OFFSET)
#define SCU_INVALIDATE (MPCORE_SCU_VBASE+SCU_INVALIDATE_OFFSET)
#define SCU_FILTERSTART (MPCORE_SCU_VBASE+SCU_FILTERSTART_OFFSET)
#define SCU_FILTEREND (MPCORE_SCU_VBASE+SCU_FILTEREND_OFFSET)
#define SCU_SAC (MPCORE_SCU_VBASE+SCU_SAC_OFFSET)
#define SCU_SNSAC (MPCORE_SCU_VBASE+SCU_SNSAC_OFFSET)
/* Register bit-field definitions *******************************************/
/* SCU Control Register (Implementation defined) */
#define SCU_CTRL_ENABLE (1 << 0) /* SCU enable */
#define SCU_CTRL_ADDRFILTER (1 << 1) /* Address filtering enable */
#define SCU_CTRL_RAMPARITY (1 << 2) /* SCU RAMs parity enable */
#define SCU_CTRL_LINFILL (1 << 3) /* SCU speculative linefill enable */
#define SCU_CTRL_PORT0 (1 << 4) /* Force all device to port0 enable */
#define SCU_CTRL_STANDBY (1 << 5) /* SCU standby enable */
#define SCU_CTRL_ICSTANDBY (1 << 6) /* IC standby enable */
/* SCU Configuration Register (Implementation defined) */
#define SCU_CONFIG_NCPUS_SHIFT 0 /* CPU number Number of CPUs present */
#define SCU_CONFIG_NCPUS_MASK (3 << SCU_CONFIG_NCPUS_SHIFT)
# define SCU_CONFIG_NCPUS(r) ((((uint32_t)(r) & SCU_CONFIG_NCPUS_MASK) >> SCU_CONFIG_NCPUS_SHIFT) + 1)
#define SCU_CONFIG_SMPCPUS_SHIFT 4 /* Processors that are in SMP or AMP mode */
#define SCU_CONFIG_SMPCPUS_MASK (15 << SCU_CONFIG_SMPCPUS_SHIFT)
# define SCU_CONFIG_CPU_SMP(n) (1 << ((n)+4))
# define SCU_CONFIG_CPU0_SMP (1 << 4)
# define SCU_CONFIG_CPU1_SMP (1 << 5)
# define SCU_CONFIG_CPU2_SMP (1 << 6)
# define SCU_CONFIG_CPU3_SMP (1 << 7)
#define SCU_CONFIG_TAGRAM_16KB 0
#define SCU_CONFIG_TAGRAM_32KB 1
#define SCU_CONFIG_TAGRAM_64KB 2
#define SCU_CONFIG_CPU0_TAGRAM_SHIFT 8 /* CPU 0 tag RAM size */
#define SCU_CONFIG_CPU0_TAGRAM_MASK (3 << SCU_CONFIG_CPU0_TAGRAM_SHIFT)
#define SCU_CONFIG_CPU1_TAGRAM_SHIFT 10 /* CPU 1 tag RAM size */
#define SCU_CONFIG_CPU1_TAGRAM_MASK (3 << SCU_CONFIG_CPU0_TAGRAM_SHIFT)
#define SCU_CONFIG_CPU2_TAGRAM_SHIFT 12 /* CPU 1 tag RAM size */
#define SCU_CONFIG_CPU2_TAGRAM_MASK (3 << SCU_CONFIG_CPU0_TAGRAM_SHIFT)
#define SCU_CONFIG_CPU3_TAGRAM_SHIFT 14 /* CPU 1 tag RAM size */
#define SCU_CONFIG_CPU3_TAGRAM_MASK (3 << SCU_CONFIG_CPU0_TAGRAM_SHIFT)
/* SCU CPU Power Status Register */
#define SCU_PWRSTATUS_NORMAL 0
#define SCU_PWRSTATUS_DORMANT 2
#define SCU_PWRSTATUS_PWROFF 3
#define SCU_PWRSTATUS_CPU0_SHIFT 0 /* CPU0 status Power status */
#define SCU_PWRSTATUS_CPU0_MASK (3 << SCU_PWRSTATUS_CPU0_SHIFT)
#define SCU_PWRSTATUS_CPU1_SHIFT 8 /* CPU1 status Power status */
#define SCU_PWRSTATUS_CPU1_MASK (3 << SCU_PWRSTATUS_CPU1_SHIFT)
#define SCU_PWRSTATUS_CPU2_SHIFT 16 /* CPU2 status Power status */
#define SCU_PWRSTATUS_CPU2_MASK (3 << SCU_PWRSTATUS_CPU2_SHIFT)
#define SCU_PWRSTATUS_CPU3_SHIFT 24 /* CPU3 status Power status */
#define SCU_PWRSTATUS_CPU3_MASK (3 << SCU_PWRSTATUS_CPU3_SHIFT)
/* SCU Invalidate All Registers in Secure State */
#define SCU_INVALIDATE_ALL_WAYS 15
#define SCU_INVALIDATE_CPU0_SHIFT 0 /* Ways that must be invalidated for CPU0 */
#define SCU_INVALIDATE_CPU0_MASK (15 << SCU_INVALIDATE_CPU0_SHIFT)
#define SCU_INVALIDATE_CPU1_SHIFT 4 /* Ways that must be invalidated for CPU1 */
#define SCU_INVALIDATE_CPU1_MASK (15 << SCU_INVALIDATE_CPU1_SHIFT)
#define SCU_INVALIDATE_CPU2_SHIFT 8 /* Ways that must be invalidated for CPU2 */
#define SCU_INVALIDATE_CPU2_MASK (15 << SCU_INVALIDATE_CPU2_SHIFT)
#define SCU_INVALIDATE_CPU3_SHIFT 12 /* Ways that must be invalidated for CPU3 */
#define SCU_INVALIDATE_CPU3_MASK (15 << SCU_INVALIDATE_CPU3_SHIFT)
/* Filtering Start Address Register Defined by FILTERSTART input */
#define SCU_FILTERSTART_SHIFT 10 /* Filtering start address */
#define SCU_FILTERSTART_MASK (0xfff << SCU_FILTERSTART_SHIFT)
/* Filtering End Address Register Defined by FILTEREND input */
#define SCU_FILTEREND_SHIFT 10 /* Filtering start address */
#define SCU_FILTEREND_MASK (0xfff << SCU_FILTEREND_SHIFT)
/* SCU Access Control (SAC) Register */
#define SCU_SAC_CPU(n) (1 << (n)) /* CPUn may access components */
/* SCU Non-secure Access Control (SNSAC) Register */
#define SCU_SNSAC_COMP_CPU(n) (1 << (n)) /* CPUn has non-secure access to components */
#define SCU_SNSAC_PTIM_CPU(n) (1 << ((n)+4)) /* CPUn has non-secure access to private timers */
#define SCU_SNSAC_GTIM_CPU(n) (1 << ((n)+8)) /* CPUn has non-secure access to global timer */
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: arm_enable_smp
*
* Description:
* Enable the SCU and make certain that current CPU is participating in
* the SMP cache coherency.
*
****************************************************************************/
void arm_enable_smp(int cpu);
#endif /* __ARCH_ARM_SRC_ARMV7_A_SCU_H */
+13
View File
@@ -53,6 +53,7 @@
#include "up_arch.h"
#include "sched/sched.h"
#include "irq/irq.h"
#include "up_internal.h"
/****************************************************************************
@@ -319,6 +320,12 @@ static void up_dumpstate(void)
#endif
#ifdef CONFIG_SMP
/* Show the CPU number */
_alert("CPU%d:\n", up_cpu_index());
#endif
/* Then dump the registers (if available) */
up_registerdump();
@@ -351,6 +358,12 @@ static void _up_assert(int errorcode)
(void)up_irq_save();
for (; ; )
{
#ifdef CONFIG_SMP
/* Try (again) to stop activity on other CPUs */
(void)spin_trylock(&g_cpu_irqlock);
#endif
#ifdef CONFIG_ARCH_LEDS
board_autoled_on(LED_PANIC);
up_mdelay(250);
@@ -165,6 +165,19 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
#ifdef CONFIG_BUILD_PROTECTED
CURRENT_REGS[REG_LR] = EXC_RETURN_PRIVTHR;
#endif
#ifdef CONFIG_SMP
/* In an SMP configuration, the interrupt disable logic also
* involves spinlocks that are configured per the TCB irqcount
* field. This is logically equivalent to enter_critical_section().
* The matching call to leave_critical_section() will be
* performed in up_sigdeliver().
*/
DEBUGASSERT(tcb->irqcount < INT16_MAX);
tcb->irqcount++;
#endif
/* And make sure that the saved context in the TCB is the same
* as the interrupt return context.
*/
@@ -211,6 +224,19 @@ void up_schedule_sigaction(struct tcb_s *tcb, sig_deliver_t sigdeliver)
#ifdef CONFIG_BUILD_PROTECTED
tcb->xcp.regs[REG_LR] = EXC_RETURN_PRIVTHR;
#endif
#ifdef CONFIG_SMP
/* In an SMP configuration, the interrupt disable logic also
* involves spinlocks that are configured per the TCB irqcount
* field. This is logically equivalent to enter_critical_section();
* The matching leave_critical_section will be performed in
* The matching call to leave_critical_section() will be performed
* in up_sigdeliver().
*/
DEBUGASSERT(tcb->irqcount < INT16_MAX);
tcb->irqcount++;
#endif
}
}
+11 -2
View File
@@ -124,9 +124,9 @@ void up_sigdeliver(void)
/* Then restore the task interrupt state */
#ifdef CONFIG_ARMV7M_USEBASEPRI
up_irq_restore((uint8_t)regs[REG_BASEPRI]);
leave_critical_section((uint8_t)regs[REG_BASEPRI]);
#else
up_irq_restore((uint16_t)regs[REG_PRIMASK]);
leave_critical_section((uint16_t)regs[REG_PRIMASK]);
#endif
/* Deliver the signal */
@@ -136,9 +136,18 @@ void up_sigdeliver(void)
/* Output any debug messages BEFORE restoring errno (because they may
* alter errno), then disable interrupts again and restore the original
* errno that is needed by the user logic (it is probably EINTR).
*
* REVISIT: In SMP mode up_irq_save() probably only disables interrupts
* on the local CPU. We do not want to call enter_critical_section()
* here, however, because we don't want this state to stick after the
* call to up_fullcontextrestore().
*
* I would prefer that all interrupts are disabled when
* up_fullcontextrestore() is called, but that may not be necessary.
*/
sinfo("Resuming\n");
(void)up_irq_save();
rtcb->pterrno = saved_errno;
+2 -2
View File
@@ -51,7 +51,7 @@
* Pre-processor Definitions
************************************************************************************/
/* intrinsics are used in these inline functions */
/* Intrinsics are used in these inline functions */
#define arm_isb(n) __asm__ __volatile__ ("isb " #n : : : "memory")
#define arm_dsb(n) __asm__ __volatile__ ("dsb " #n : : : "memory")
@@ -61,7 +61,7 @@
#define ARM_ISB() arm_isb(15)
#define ARM_DMB() arm_dmb(15)
/************************************************************************************
/************************************************************************************
* Inline Functions
************************************************************************************/
+20
View File
@@ -110,3 +110,23 @@ config C5471_BASET10
bool "10BaseT FullDuplex"
endchoice
choice
prompt "Ethernet work queue"
default C5471_LPWORK if SCHED_LPWORK
default C5471_HPWORK if !SCHED_LPWORK && SCHED_HPWORK
depends on SCHED_WORKQUEUE
---help---
Work queue support is required to use the Ethernet driver. If the
low priority work queue is available, then it should be used by the
driver.
config C5471_HPWORK
bool "High priority"
depends on SCHED_HPWORK
config C5471_LPWORK
bool "Low priority"
depends on SCHED_LPWORK
endchoice # Work queue
File diff suppressed because it is too large Load Diff
+10
View File
@@ -191,6 +191,11 @@
# define _DATA_INIT &_eronly
# define _START_DATA &_sdata
# define _END_DATA &_edata
#ifdef CONFIG_SMP
# define _START_NOCACHE &_snocache
# define _END_NOCACHE &_enocache
#endif
#endif
/* This is the value used to mark the stack for subsequent stack monitoring
@@ -279,6 +284,11 @@ EXTERN uint32_t _edata; /* End+1 of .data */
EXTERN uint32_t _sbss; /* Start of .bss */
EXTERN uint32_t _ebss; /* End+1 of .bss */
#ifdef CONFIG_SMP
EXTERN uint32_t _snocache; /* Start of .nocache */
EXTERN uint32_t _enocache; /* End+1 of .nocache */
#endif
/* Sometimes, functions must be executed from RAM. In this case, the following
* macro may be used (with GCC!) to specify a function that will execute from
* RAM. For example,
+1
View File
@@ -81,6 +81,7 @@ CMN_CSRCS += arm_unblocktask.c arm_undefinedinsn.c
ifeq ($(CONFIG_SMP),y)
CMN_CSRCS += arm_cpuindex.c arm_cpustart.c arm_cpupause.c arm_cpuidlestack.c
CMN_CSRCS += arm_scu.c
endif
ifeq ($(CONFIG_DEBUG_IRQ_INFO),y)
+122 -8
View File
@@ -122,6 +122,18 @@
#define IMX_MMDCDDR_PSECTION 0x10000000 /* 10000000-ffffffff 3840 MB MMDC-DDR Controller */
/* 10000000-7fffffff 1792 MB */
/* By default, NuttX uses a 1-1 memory mapping. So the unused, reserved
* address in the top-level memory map are candidates for other mapping uses:
*
* 00018000-000fffff Reserved -- Not used
* 00400000-007fffff Reserved -- Used as the virtual address an inter-CPU,
* un-cached memory region in SMP
* configurations
* 00d00000-00ffffff Reserved -- Not used
* 0220c000-023fffff Reserved -- Not used
* 80000000-efffffff Reserved -- Level 2 page table (See below)
*/
/* i.MX6 DMA PSECTION Offsets */
#define IMX_CAAMRAM_OFFSET 0x00000000 /* 00000000-00003fff 16 KB CAAM (16K secure RAM) */
@@ -897,7 +909,7 @@
* 0x80000000-0xefffffff: Undefined (1.75 GB)
*
* That is the offset where the main L2 page tables will be positioned. This
* corresponds to page table offsets 0x000002000 up to 0x000003c00. That
* corresponds to page table offsets 0x00002000 up to 0x00003c00. That
* is 1792 entries, each mapping 4KB of address for a total of 7MB of virtual
* address space)
*
@@ -917,7 +929,21 @@
* the address space.
*/
#define INTERCPU_L2_PAGES 1 /* Pages allowed for inter-processor communications */
#ifndef CONFIG_ARCH_LOWVECTORS
/* Memory map
* VIRTUAL ADDRESS RANGE L1 PG TABLE L2 PG TABLE DESCRIPTION
* START END OFFSET SIZE
* ---------- ---------- ------------ ----------------------------
* 0x80000000 0x803fffff 0x000002000 0x000000400 Vectors (1MiB)
* 0x80100000 0x806fffff 0x000002400 0x000001800 Paging (6MiB)
*
* If SMP is enabled, then 1MiB of address spaces for the INTERCPU_L2_PAGES
* pages are taken from the end of the Paging L2 page table to hold non-
* cacheable, inter-processor communication data.
*/
/* Vector L2 page table offset/size */
# define VECTOR_L2_OFFSET 0x000002000
@@ -933,16 +959,44 @@
# define VECTOR_L2_END_PADDR (VECTOR_L2_PBASE + VECTOR_L2_SIZE)
# define VECTOR_L2_END_VADDR (VECTOR_L2_VBASE + VECTOR_L2_SIZE)
/* Paging L2 page table offset/size */
# if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Paging L2 page table offset/size */
# define PGTABLE_L2_OFFSET 0x000002400
# define PGTABLE_L2_SIZE 0x000001800
# define PGTABLE_L2_OFFSET 0x000002400
# define PGTABLE_L2_SIZE 0x000001400
# else
/* Paging L2 page table offset/size */
# define PGTABLE_L2_OFFSET 0x000002400
# define PGTABLE_L2_SIZE 0x000001800
# endif
#else
/* Memory map
* VIRTUAL ADDRESS RANGE L1 PG TABLE L2 PG TABLE DESCRIPTION
* START END OFFSET SIZE
* ---------- ---------- ------------ ----------------------------
* 0x80000000 0x806fffff 0x000002000 0x000001c00 Paging (7MiB)
*
* If SMP is enabled, then 1MiB of address spaces for the INTERCPU_L2_PAGES
* pages are taken from the end of the Paging L2 page table to hold non-
* cacheable, inter-processor communication data.
*/
# if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Paging L2 page table offset/size */
# define PGTABLE_L2_OFFSET 0x000002000
# define PGTABLE_L2_SIZE 0x000001c00
# define PGTABLE_L2_OFFSET 0x000002000
# define PGTABLE_L2_SIZE 0x000001800
# else
/* Paging L2 page table offset/size */
# define PGTABLE_L2_OFFSET 0x000002000
# define PGTABLE_L2_SIZE 0x000001c00
# endif
#endif
/* Paging L2 page table base addresses
@@ -959,6 +1013,23 @@
#define PGTABLE_L2_END_PADDR (PGTABLE_L2_PBASE + PGTABLE_L2_SIZE)
#define PGTABLE_L2_END_VADDR (PGTABLE_L2_VBASE + PGTABLE_L2_SIZE)
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Non-cached inter-processor communication data */
# define INTERCPU_L2_OFFSET (PGTABLE_L2_OFFSET + PGTABLE_L2_SIZE)
# define INTERCPU_L2_SIZE (0x00000400)
/* Non-cached inter-processor communication page table base addresses */
# define INTERCPU_L2_PBASE (PGTABLE_BASE_PADDR + INTERCPU_L2_OFFSET)
# define INTERCPU_L2_VBASE (PGTABLE_BASE_VADDR + INTERCPU_L2_OFFSET)
/* Non-cached inter-processor communication end addresses */
# define INTERCPU_L2_END_PADDR (INTERCPU_L2_PBASE + INTERCPU_L2_SIZE)
# define INTERCPU_L2_END_VADDR (INTERCPU_L2_VBASE + INTERCPU_L2_SIZE)
#endif
/* Base address of the interrupt vector table.
*
* IMX_VECTOR_PADDR - Unmapped, physical address of vector table in SRAM
@@ -974,19 +1045,62 @@
*/
#ifdef CONFIG_ARCH_LOWVECTORS /* Vectors located at 0x0000:0000 */
/* Vectors will always lie at the beginnin of OCRAM */
/* Vectors will always lie at the beginning of OCRAM
*
* OCRAM Memory Map:
* ---------- ---------- ---------------------------
* START END CONTENT
* ---------- ---------- ---------------------------
* 0x00000000 0x00010000 Vectors (VECTOR_TABLE_SIZE)
* 0x00010000 0x00011000 Inter-CPU communications
* 0x00011000 0x0003c000 Unused
* 0x0003c000 0x00004000 Page table (PGTABLE_SIZE)
*/
# define IMX_VECTOR_PADDR IMX_OCRAM_PBASE
# define IMX_VECTOR_VSRAM IMX_OCRAM_VBASE
# define IMX_VECTOR_VADDR 0x00000000
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Inter-processor communications.
*
* NOTICE that we use the unused virtual address space at 0x00400000 for
* the inter-CPU virtual communication area.
*/
# define INTERCPU_PADDR (IMX_VECTOR_PADDR + VECTOR_TABLE_SIZE)
# define INTERCPU_VADDR (0x00400000)
# define INTERCPU_SIZE (INTERCPU_L2_PAGES << 12)
# define INTERCPU_VSRAM (IMX_VECTOR_VSRAM + VECTOR_TABLE_SIZE)
#endif
#else /* Vectors located at 0xffff:0000 -- this probably does not work */
/* OCRAM Memory Map:
* ---------- ---------- ---------------------------
* START END CONTENT
* ---------- ---------- ---------------------------
* 0x00000000 0x00004000 Page table (PGTABLE_SIZE)
* 0x00004000 0x0002f000 Unused
* 0x0002f000 0x00030000 Inter-CPU communications
* 0x00030000 0x00010000 Vectors (VECTOR_TABLE_SIZE)
*/
# define IMX_VECTOR_PADDR (IMX_OCRAM_PBASE + IMX_OCRAM_SIZE - VECTOR_TABLE_SIZE)
# define IMX_VECTOR_VSRAM (IMX_OCRAM_VBASE + IMX_OCRAM_SIZE - VECTOR_TABLE_SIZE)
# define IMX_VECTOR_VADDR 0xffff0000
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Inter-processor communications
*
* NOTICE that we use the unused virtual address space at 0x00400000 for
* the inter-CPU virtual communication area.
*/
# define INTERCPU_PADDR (IMX_VECTOR_PADDR - INTERCPU_L2_SIZE)
# define INTERCPU_VADDR (0x00400000)
# define INTERCPU_SIZE (INTERCPU_L2_PAGES << 12)
# define INTERCPU_VSRAM (IMX_VECTOR_VSRAM - INTERCPU_L2_SIZE)
#endif
#endif
/************************************************************************************
+109 -21
View File
@@ -52,6 +52,7 @@
#include "chip.h"
#include "arm.h"
#include "mmu.h"
#include "scu.h"
#include "cache.h"
#include "fpu.h"
#include "up_internal.h"
@@ -64,6 +65,16 @@
#include "imx_serial.h"
#include "imx_boot.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifdef CONFIG_DEBUG_FEATURES
# define PROGRESS(c) imx_lowputc(c)
#else
# define PROGRESS(c)
#endif
/****************************************************************************
* Public Data
****************************************************************************/
@@ -224,6 +235,48 @@ static void imx_vectormapping(void)
# define imx_vectormapping()
#endif
/****************************************************************************
* Name: imx_intercpu_mapping
*
* Description:
* Setup a special mapping for the non-cached, inter-cpu communications
* area.
*
****************************************************************************/
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
static void imx_intercpu_mapping(void)
{
uint32_t intercpu_paddr = INTERCPU_PADDR & PTE_SMALL_PADDR_MASK;
uint32_t intercpu_vaddr = INTERCPU_VADDR & PTE_SMALL_PADDR_MASK;
uint32_t end_paddr = INTERCPU_PADDR + INTERCPU_SIZE;
DEBUGASSERT(intercpu_vaddr == (uint32_t)&_snocache);
/* We want to keep the inter-cpu region in on-chip RAM (OCRAM). The
* i.MX6 has 256Kb of OCRAM positioned at physical address 0x0090:0000.
*/
while (intercpu_paddr < end_paddr)
{
mmu_l2_setentry(INTERCPU_L2_VBASE, intercpu_paddr, intercpu_vaddr,
MMU_L2_INTERCPUFLAGS);
intercpu_paddr += 4096;
intercpu_vaddr += 4096;
}
/* Now set the level 1 descriptor to refer to the level 2 page table. */
mmu_l1_setentry(INTERCPU_L2_PBASE & PMD_PTE_PADDR_MASK,
INTERCPU_VADDR & PMD_PTE_PADDR_MASK,
MMU_L1_INTERCPUFLAGS);
}
#else
/* No inter-cpu communications area */
# define imx_intercpu_mapping()
#endif
/****************************************************************************
* Name: imx_copyvectorblock
*
@@ -388,8 +441,10 @@ static inline void imx_wdtdisable(void)
void arm_boot(void)
{
#ifdef CONFIG_ARCH_RAMFUNCS
#if defined(CONFIG_ARCH_RAMFUNCS)
const uint32_t *src;
#endif
#if defined(CONFIG_ARCH_RAMFUNCS) || defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
uint32_t *dest;
#endif
@@ -398,7 +453,7 @@ void arm_boot(void)
*/
imx_setupmappings();
imx_lowputc('A');
PROGRESS('A');
/* Make sure that all other CPUs are in the disabled state. This is a
* formality because the other CPUs are actually running then we have
@@ -406,13 +461,30 @@ void arm_boot(void)
*/
imx_cpu_disable();
PROGRESS('B');
#ifdef CONFIG_SMP
/* Enable SMP cache coherency for CPU0 */
arm_enable_smp(0);
PROGRESS('C');
#endif
/* Provide a special mapping for the OCRAM interrupt vector positioned in
* high memory.
*/
imx_vectormapping();
imx_lowputc('B');
PROGRESS('D');
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Provide a special mapping for the OCRAM interrupt vector positioned in
* high memory.
*/
imx_intercpu_mapping();
PROGRESS('E');
#endif
#ifdef CONFIG_ARCH_RAMFUNCS
/* Copy any necessary code sections from FLASH to RAM. The correct
@@ -426,14 +498,14 @@ void arm_boot(void)
*dest++ = *src++;
}
imx_lowputc('C');
PROGRESS('F');
/* Flush the copied RAM functions into physical RAM so that will
* be available when fetched into the I-Cache.
*/
arch_clean_dcache((uintptr_t)&_sramfuncs, (uintptr_t)&_eramfuncs)
imx_lowputc('D');
PROGRESS('G');
#endif
/* Setup up vector block. _vector_start and _vector_end are exported from
@@ -441,37 +513,35 @@ void arm_boot(void)
*/
imx_copyvectorblock();
imx_lowputc('E');
PROGRESS('H');
/* Disable the watchdog timer */
imx_wdtdisable();
imx_lowputc('F');
PROGRESS('I');
/* Initialize clocking to settings provided by board-specific logic */
imx_clockconfig();
imx_lowputc('G');
PROGRESS('J');
#ifdef CONFIG_ARCH_FPU
/* Initialize the FPU */
arm_fpuconfig();
imx_lowputc('H');
PROGRESS('K');
#endif
/* Perform board-specific initialization, This must include:
*
* - Initialization of board-specific memory resources (e.g., SDRAM)
* - Configuration of board specific resources (PIOs, LEDs, etc).
/* Perform board-specific memroy initialization, This must include
* initialization of board-specific memory resources (e.g., SDRAM)
*
* NOTE: We must use caution prior to this point to make sure that
* the logic does not access any global variables that might lie
* in SDRAM.
*/
imx_board_initialize();
imx_lowputc('I');
imx_memory_initialize();
PROGRESS('L');
#ifdef NEED_SDRAM_REMAPPING
/* SDRAM was configured in a temporary state to support low-level
@@ -480,7 +550,7 @@ void arm_boot(void)
*/
imx_remap();
imx_lowputc('J');
PROGRESS('M');
#endif
#ifdef CONFIG_BOOT_SDRAM_DATA
@@ -489,13 +559,31 @@ void arm_boot(void)
*/
arm_data_initialize();
imx_lowputc('K');
PROGRESS('N');
#endif
/* Perform board-specific device initialization. This would include
* configuration of board specific resources such as GPIOs, LEDs, etc.
*/
imx_board_initialize();
PROGRESS('O');
#if defined(CONFIG_SMP) && defined(SMP_INTERCPU_NONCACHED)
/* Initialize the uncached, inter-CPU communications area */
for (dest = &_snocache; dest < &_enocache; )
{
*dest++ = 0;
}
PROGRESS('P');
#endif
/* Perform common, low-level chip initialization (might do nothing) */
imx_lowsetup();
imx_lowputc('L');
PROGRESS('Q');
#ifdef USE_EARLYSERIALINIT
/* Perform early serial initialization if we are going to use the serial
@@ -503,7 +591,7 @@ void arm_boot(void)
*/
imx_earlyserialinit();
imx_lowputc('M');
PROGRESS('R');
#endif
/* Now we can enable all other CPUs. The enabled CPUs will start execution
@@ -512,6 +600,6 @@ void arm_boot(void)
*/
imx_cpu_enable();
imx_lowputc('N');
imx_lowputc('\n');
PROGRESS('S');
PROGRESS('\n');
}
+26 -3
View File
@@ -110,14 +110,37 @@ void imx_cpu_enable(void);
# define imx_cpu_enable()
#endif
/****************************************************************************
* Name: imx_memory_initialize
*
* Description:
* All i.MX6 architectures must provide the following entry point. This
* entry point is called early in the initialization before memory has
* been configured. This board-specific function is responsible for
* configuring any on-board memories.
*
* Logic in imx_memory_initialize must be careful to avoid using any
* global variables because those will be uninitialized at the time this
* function is called.
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
****************************************************************************/
void imx_memory_initialize(void);
/****************************************************************************
* Name: imx_board_initialize
*
* Description:
* All i.MX6 architectures must provide the following entry point. This
* entry point is called early in the initialization -- after all memory
* has been configured and mapped but before any devices have been
* initialized.
* entry point is called in the initialization phase -- after
* imx_memory_initialize and after all memory has been configured and
* mapped but before any devices have been initialized.
*
* Input Parameters:
* None
+5 -5
View File
@@ -51,9 +51,9 @@
#include "chip/imx_src.h"
#include "sctlr.h"
#include "smp.h"
#include "scu.h"
#include "fpu.h"
#include "gic.h"
#include "cp15_cacheops.h"
#ifdef CONFIG_SMP
@@ -260,6 +260,10 @@ void imx_cpu_enable(void)
void arm_cpu_boot(int cpu)
{
/* Enable SMP cache coherency for the CPU */
arm_enable_smp(cpu);
#ifdef CONFIG_ARCH_FPU
/* Initialize the FPU */
@@ -297,10 +301,6 @@ void arm_cpu_boot(int cpu)
(void)up_irq_enable();
#endif
/* Invalidate CPUn L1 so that is will be reloaded from coherent L2. */
cp15_invalidate_dcache_all();
/* The next thing that we expect to happen is for logic running on CPU0
* to call up_cpu_start() which generate an SGI and a context switch to
* the configured NuttX IDLE task.
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -134,11 +134,11 @@ void up_irqinitialize(void)
CURRENT_REGS = NULL;
#ifndef CONFIG_SUPPRESS_INTERRUPTS
#ifdef CONFIG_IMX6_PIO_IRQ
/* Initialize logic to support a second level of interrupt decoding for
* PIO pins.
*/
#ifdef CONFIG_IMX6_PIO_IRQ
imx_gpioirq_initialize();
#endif
-1
View File
@@ -254,7 +254,6 @@ config KINETIS_ENET
select ARCH_HAVE_NETDEV_STATISTICS
select NET
select NETDEVICES
select NET_MULTIBUFFER
---help---
Support Ethernet (K6x only)
+68 -225
View File
@@ -53,14 +53,11 @@
#include <nuttx/wdog.h>
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#ifdef CONFIG_NET_PKT
# include <nuttx/net/pkt.h>
#endif
@@ -84,13 +81,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_KINETIS_EMAC_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_KINETIS_EMAC_LPWORK)
@@ -119,10 +115,6 @@
#define NENET_NBUFFERS \
(CONFIG_KINETIS_ENETNTXBUFFERS+CONFIG_KINETIS_ENETNRXBUFFERS)
#ifndef CONFIG_NET_MULTIBUFFER
# error "CONFIG_NET_MULTIBUFFER is required in the configuration"
#endif
/* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per
* second.
*/
@@ -223,9 +215,7 @@ struct kinetis_driver_s
uint8_t phyaddr; /* Selected PHY address */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
struct enet_desc_s *txdesc; /* A pointer to the list of TX descriptor */
struct enet_desc_s *rxdesc; /* A pointer to the list of RX descriptors */
@@ -283,24 +273,15 @@ static int kinetis_txpoll(struct net_driver_s *dev);
static void kinetis_receive(FAR struct kinetis_driver_s *priv);
static void kinetis_txdone(FAR struct kinetis_driver_s *priv);
static inline void kinetis_interrupt_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_interrupt_work(FAR void *arg);
#endif
static int kinetis_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
static inline void kinetis_txtimeout_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_txtimeout_work(FAR void *arg);
#endif
static void kinetis_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void kinetis_poll_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_poll_work(FAR void *arg);
#endif
static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
@@ -308,10 +289,7 @@ static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...);
static int kinetis_ifup(struct net_driver_s *dev);
static int kinetis_ifdown(struct net_driver_s *dev);
static inline void kinetis_txavail_process(FAR struct kinetis_driver_s *priv);
#ifdef CONFIG_NET_NOINTS
static void kinetis_txavail_work(FAR void *arg);
#endif
static int kinetis_txavail(struct net_driver_s *dev);
#ifdef CONFIG_NET_IGMP
@@ -828,27 +806,31 @@ static void kinetis_txdone(FAR struct kinetis_driver_s *priv)
}
/****************************************************************************
* Function: kinetis_interrupt_process
* Function: kinetis_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
static inline void kinetis_interrupt_process(FAR struct kinetis_driver_s *priv)
static void kinetis_interrupt_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
uint32_t pending;
/* Process pending Ethernet interrupts */
net_lock();
/* Get the set of unmasked, pending interrupt. */
pending = getreg32(KINETIS_ENET_EIR) & getreg32(KINETIS_ENET_EIMR);
@@ -896,36 +878,8 @@ static inline void kinetis_interrupt_process(FAR struct kinetis_driver_s *priv)
putreg32(ENET_RDAR, KINETIS_ENET_RDAR);
}
}
/****************************************************************************
* Function: kinetis_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* The network is locked.
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_interrupt_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
state = net_lock();
kinetis_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts */
@@ -936,7 +890,6 @@ static void kinetis_interrupt_work(FAR void *arg)
up_enable_irq(KINETIS_IRQ_EMACRX);
up_enable_irq(KINETIS_IRQ_EMACMISC);
}
#endif
/****************************************************************************
* Function: kinetis_interrupt
@@ -962,7 +915,6 @@ static int kinetis_interrupt(int irq, FAR void *context)
{
register FAR struct kinetis_driver_s *priv = &g_enet[0];
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. Because Ethernet interrupts are
* also disabled if the TX timeout event occurs, there can be no race
* condition here.
@@ -991,51 +943,9 @@ static int kinetis_interrupt(int irq, FAR void *context)
/* Schedule to perform the interrupt processing on the worker thread. */
work_queue(ETHWORK, &priv->work, kinetis_interrupt_work, priv, 0);
#else
/* Process the interrupt now */
kinetis_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: kinetis_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
****************************************************************************/
static inline void kinetis_txtimeout_process(FAR struct kinetis_driver_s *priv)
{
/* Increment statistics and dump debug info */
NETDEV_TXTIMEOUTS(&priv->dev);
/* Take the interface down and bring it back up. The is the most agressive
* hardware reset.
*/
(void)kinetis_ifdown(&priv->dev);
(void)kinetis_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->dev, kinetis_txpoll);
}
/****************************************************************************
* Function: kinetis_txtimeout_work
*
@@ -1053,19 +963,27 @@ static inline void kinetis_txtimeout_process(FAR struct kinetis_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_txtimeout_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Increment statistics and dump debug info */
state = net_lock();
kinetis_txtimeout_process(priv);
net_unlock(state);
net_lock();
NETDEV_TXTIMEOUTS(&priv->dev);
/* Take the interface down and bring it back up. The is the most agressive
* hardware reset.
*/
(void)kinetis_ifdown(&priv->dev);
(void)kinetis_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
(void)devif_poll(&priv->dev, kinetis_txpoll);
net_unlock();
}
#endif
/****************************************************************************
* Function: kinetis_txtimeout_expiry
@@ -1090,7 +1008,6 @@ static void kinetis_txtimeout_expiry(int argc, uint32_t arg, ...)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. This will prevent some race
* conditions with interrupt work. There is still a potential race
* condition with interrupt work that is already queued and in progress.
@@ -1110,50 +1027,6 @@ static void kinetis_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, kinetis_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
kinetis_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: kinetis_poll_process
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
*
****************************************************************************/
static inline void kinetis_poll_process(FAR struct kinetis_driver_s *priv)
{
/* Check if there is there is a transmission in progress. We cannot perform
* the TX poll if he are unable to accept another packet for transmission.
*/
if (!kinetics_txringfull(priv))
{
/* If so, update TCP timing states and poll the network for new XMIT data. Hmmm..
* might be bug here. Does this mean if there is a transmit in progress,
* we will missing TCP time state updates?
*/
(void)devif_timer(&priv->dev, kinetis_txpoll);
}
/* Setup the watchdog poll timer again in any case */
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer_expiry,
1, (wdparm_t)priv);
}
/****************************************************************************
@@ -1173,19 +1046,31 @@ static inline void kinetis_poll_process(FAR struct kinetis_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_poll_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Check if there is there is a transmission in progress. We cannot perform
* the TX poll if he are unable to accept another packet for transmission.
*/
state = net_lock();
kinetis_poll_process(priv);
net_unlock(state);
net_lock();
if (!kinetics_txringfull(priv))
{
/* If so, update TCP timing states and poll the network for new XMIT data. Hmmm..
* might be bug here. Does this mean if there is a transmit in progress,
* we will missing TCP time state updates?
*/
(void)devif_timer(&priv->dev, kinetis_txpoll);
}
/* Setup the watchdog poll timer again in any case */
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer_expiry,
1, (wdparm_t)priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: kinetis_polltimer_expiry
@@ -1209,7 +1094,6 @@ static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -1229,12 +1113,6 @@ static void kinetis_polltimer_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, KINETIS_WDDELAY, kinetis_polltimer_expiry,
1, (wdparm_t)arg);
}
#else
/* Process the interrupt now */
kinetis_poll_process(priv);
#endif
}
/****************************************************************************
@@ -1420,49 +1298,6 @@ static int kinetis_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: kinetis_txavail_process
*
* Description:
* Perform an out-of-cycle poll.
*
* Parameters:
* dev - Reference to the NuttX driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Called in normal user mode
*
****************************************************************************/
static inline void kinetis_txavail_process(FAR struct kinetis_driver_s *priv)
{
net_lock_t state;
/* Ignore the notification if the interface is not yet up */
state = net_lock();
if (priv->bifup)
{
/* Check if there is room in the hardware to hold another outgoing
* packet.
*/
if (!kinetics_txringfull(priv))
{
/* No, there is space for another transfer. Poll the network for new
* XMIT data.
*/
(void)devif_poll(&priv->dev, kinetis_txpoll);
}
}
net_unlock(state);
}
/****************************************************************************
* Function: kinetis_txavail_work
*
@@ -1480,16 +1315,31 @@ static inline void kinetis_txavail_process(FAR struct kinetis_driver_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void kinetis_txavail_work(FAR void *arg)
{
FAR struct kinetis_driver_s *priv = (FAR struct kinetis_driver_s *)arg;
/* Perform the poll */
/* Ignore the notification if the interface is not yet up */
kinetis_txavail_process(priv);
net_lock();
if (priv->bifup)
{
/* Check if there is room in the hardware to hold another outgoing
* packet.
*/
if (!kinetics_txringfull(priv))
{
/* No, there is space for another transfer. Poll the network for new
* XMIT data.
*/
(void)devif_poll(&priv->dev, kinetis_txpoll);
}
}
net_unlock();
}
#endif
/****************************************************************************
* Function: kinetis_txavail
@@ -1515,7 +1365,6 @@ static int kinetis_txavail(struct net_driver_s *dev)
FAR struct kinetis_driver_s *priv =
(FAR struct kinetis_driver_s *)dev->d_private;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions and we will have to ignore the Tx
* availability action.
@@ -1528,12 +1377,6 @@ static int kinetis_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, kinetis_txavail_work, priv, 0);
}
#else
/* Perform the out-of-cycle poll now */
kinetis_txavail_process(priv);
#endif
return OK;
}
+1 -1
View File
@@ -136,7 +136,7 @@
# endif /* LPC17_HAVE_BANK1 && LPC17_BANK1_HEAPSIZE */
# else /* !LPC17_BANK0_HEAPSIZE */
/* We have Bnak 0, but no memory is available for the heap there.
/* We have Bank 0, but no memory is available for the heap there.
* Do we have Bank 1? Is any heap memory available in Bank 1?
*/
File diff suppressed because it is too large Load Diff
+6 -3
View File
@@ -70,12 +70,12 @@
#define LPC43_GPDMA_CONTROL_CHOFFSET 0x000c /* DMA Channel Control Register */
#define LPC43_GPDMA_CONFIG_CHOFFSET 0x0010 /* DMA Channel Configuration Register */
#define LPC43_GPDMA_CHOFFSET(n) (0x0100 ((n) << 5))
#define LPC43_GPDMA_CHOFFSET(n) (0x0100 + ((n) << 5))
#define LPC43_GPDMA_SRCADDR_OFFSET(n) (LPC43_GPDMA_CHOFFSET(n)+LPC43_GPDMA_SRCADDR_CHOFFSET)
#define LPC43_GPDMA_DESTADDR_OFFSET(n) (LPC43_GPDMA_CHOFFSET(n)+LPC43_GPDMA_DESTADDR_CHOFFSET)
#define LPC43_GPDMA_LLI_OFFSET(n) (LPC43_GPDMA_CHOFFSET(n)+LPC43_GPDMA_LLI_CHOFFSET)
#define LPC43_GPDMA_CONTROL_OFFSET(n) (LPC43_GPDMA_CHOFFSET(n)+LPC43_GPDMA_CONTROL_CHOFFSET)
#define LPC43_GPDMA_CONFIG_OFFSET(n) (LPC43_GPDMA_CHOFFSET(n)+LPC43_GPDMA_CONFIG_CHOFFSET)
#define LPC43_GPDMA_CONFIG_OFFSET_(n) (LPC43_GPDMA_CHOFFSET(n)+LPC43_GPDMA_CONFIG_CHOFFSET)
#define LPC43_GPDMA_SRCADDR0_OFFSET 0x0100 /* DMA Channel 0 Source Address Register */
#define LPC43_GPDMA_DESTADDR0_OFFSET 0x0104 /* DMA Channel 0 Destination Address Register */
@@ -149,7 +149,7 @@
#define LPC43_GPDMA_DESTADDR(n) (LPC43_DMA_BASE+LPC43_GPDMA_DESTADDR_OFFSET(n))
#define LPC43_GPDMA_LLI(n) (LPC43_DMA_BASE+LPC43_GPDMA_LLI_OFFSET(n))
#define LPC43_GPDMA_CONTROL(n) (LPC43_DMA_BASE+LPC43_GPDMA_CONTROL_OFFSET(n))
#define LPC43_GPDMA_CONFIG(n) (LPC43_DMA_BASE+LPC43_GPDMA_CONFIG_OFFSET(n))
#define LPC43_GPDMA_CONFIG_(n) (LPC43_DMA_BASE+LPC43_GPDMA_CONFIG_OFFSET_(n))
#define LPC43_GPDMA_SRCADDR0 (LPC43_DMA_BASE+LPC43_GPDMA_SRCADDR0_OFFSET)
#define LPC43_GPDMA_DESTADDR0 (LPC43_DMA_BASE+LPC43_GPDMA_DESTADDR0_OFFSET)
@@ -203,6 +203,9 @@
/* Common macros for DMA channel and source bit settings */
#define DMACH_ALL (0xff)
#define LPC43_NDMACH 8 /* Eight DMA channels */
#define LPC43_NDMAREQ (16) /* The number of DMA requests */
#define GPDMA_CHANNEL(n) (1 << (n)) /* Bits 0-7 correspond to DMA channel 0-7 */
#define GPDMA_SOURCE(n) (1 << (n)) /* Bits 0-15 correspond to DMA source 0-15 */
#define GPDMA_REQUEST(n) (1 << (n)) /* Bits 0-15 correspond to DMA request 0-15 */
+4 -3
View File
@@ -143,10 +143,11 @@
#define SDMMC_CTRL_CEATAINT (1 << 11) /* Bit 11: CE-ATA device interrupts enabled */
/* Bits 12-15: Reserved */
#define SDMMC_CTRL_CDVA0 (1 << 16) /* Bit 16: Controls SD_VOLT0 pin */
#define SDMMC_CTRL_CDVA0 (1 << 17) /* Bit 17: Controls SD_VOLT1 pin */
#define SDMMC_CTRL_CDVA0 (1 << 18) /* Bit 18: Controls SD_VOLT2 pin */
#define SDMMC_CTRL_CDVA1 (1 << 17) /* Bit 17: Controls SD_VOLT1 pin */
#define SDMMC_CTRL_CDVA2 (1 << 18) /* Bit 18: Controls SD_VOLT2 pin */
/* Bits 19-23: Reserved */
#define SDMMC_CTRL_INTDMA (1 << 25) /* Bit 24: SD/MMC DMA use */
/* Bit 24: Reserved - always write it as 0 */
#define SDMMC_CTRL_INTDMA (1 << 25) /* Bit 25: SD/MMC DMA use */
/* Bits 26-31: Reserved */
/* Power Enable Register (PWREN) */
+48 -222
View File
@@ -53,11 +53,7 @@
#include <nuttx/arch.h>
#include <nuttx/irq.h>
#include <nuttx/wdog.h>
#ifdef CONFIG_NET_NOINTS
# include <nuttx/wqueue.h>
#endif
#include <nuttx/wqueue.h>
#include <nuttx/net/mii.h>
#include <nuttx/net/arp.h>
#include <nuttx/net/netdev.h>
@@ -87,13 +83,12 @@
* is required.
*/
#if defined(CONFIG_NET_NOINTS) && !defined(CONFIG_SCHED_WORKQUEUE)
#if !defined(CONFIG_SCHED_WORKQUEUE)
# error Work queue support is required
#endif
#else
/* Select work queue */
/* Select work queue */
#if defined(CONFIG_SCHED_WORKQUEUE)
# if defined(CONFIG_LPC43_ETHERNET_HPWORK)
# define ETHWORK HPWORK
# elif defined(CONFIG_LPC43_ETHERNET_LPWORK)
@@ -164,12 +159,6 @@
#undef CONFIG_LPC43_ETH_ENHANCEDDESC
#undef CONFIG_LPC43_ETH_HWCHECKSUM
/* Ethernet buffer sizes, number of buffers, and number of descriptors */
#ifndef CONFIG_NET_MULTIBUFFER
# error "CONFIG_NET_MULTIBUFFER is required"
#endif
/* Add 4 to the configured buffer size to account for the 2 byte checksum
* memory needed at the end of the maximum size packet. Buffer sizes must
* be an even multiple of 4, 8, or 16 bytes (depending on buswidth). We
@@ -530,9 +519,7 @@ struct lpc43_ethmac_s
uint8_t fduplex : 1; /* Full (vs. half) duplex */
WDOG_ID txpoll; /* TX poll timer */
WDOG_ID txtimeout; /* TX timeout timer */
#ifdef CONFIG_NET_NOINTS
struct work_s work; /* For deferring work to the work queue */
#endif
/* This holds the information visible to the NuttX network */
@@ -605,34 +592,26 @@ static int lpc43_recvframe(FAR struct lpc43_ethmac_s *priv);
static void lpc43_receive(FAR struct lpc43_ethmac_s *priv);
static void lpc43_freeframe(FAR struct lpc43_ethmac_s *priv);
static void lpc43_txdone(FAR struct lpc43_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc43_interrupt_work(FAR void *arg);
#endif
static int lpc43_interrupt(int irq, FAR void *context);
/* Watchdog timer expirations */
static inline void lpc43_txtimeout_process(FAR struct lpc43_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc43_txtimeout_work(FAR void *arg);
#endif
static void lpc43_txtimeout_expiry(int argc, uint32_t arg, ...);
static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc43_poll_work(FAR void *arg);
#endif
static void lpc43_poll_expiry(int argc, uint32_t arg, ...);
/* NuttX callback functions */
static int lpc43_ifup(struct net_driver_s *dev);
static int lpc43_ifdown(struct net_driver_s *dev);
static inline void lpc43_txavail_process(FAR struct lpc43_ethmac_s *priv);
#ifdef CONFIG_NET_NOINTS
static void lpc43_txavail_work(FAR void *arg);
#endif
static int lpc43_txavail(struct net_driver_s *dev);
#if defined(CONFIG_NET_IGMP) || defined(CONFIG_NET_ICMPv6)
static int lpc43_addmac(struct net_driver_s *dev, FAR const uint8_t *mac);
#endif
@@ -1906,29 +1885,32 @@ static void lpc43_txdone(FAR struct lpc43_ethmac_s *priv)
}
/****************************************************************************
* Function: lpc43_interrupt_process
* Function: lpc43_interrupt_work
*
* Description:
* Interrupt processing. This may be performed either within the interrupt
* handler or on the worker thread, depending upon the configuration
* Perform interrupt related work from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void lpc43_interrupt_process(FAR struct lpc43_ethmac_s *priv)
static void lpc43_interrupt_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
uint32_t dmasr;
DEBUGASSERT(priv);
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */
net_lock();
dmasr = lpc43_getreg(LPC43_ETH_DMASTAT);
/* Mask only enabled interrupts. This depends on the fact that the interrupt
@@ -1980,7 +1962,6 @@ static inline void lpc43_interrupt_process(FAR struct lpc43_ethmac_s *priv)
/* Handle error interrupt only if CONFIG_DEBUG_NET is eanbled */
#ifdef CONFIG_DEBUG_NET
/* Check if there are pending "abnormal" interrupts */
if ((dmasr & ETH_DMAINT_AIS) != 0)
@@ -1997,45 +1978,13 @@ static inline void lpc43_interrupt_process(FAR struct lpc43_ethmac_s *priv)
lpc43_putreg(ETH_DMAINT_AIS, LPC43_ETH_DMASTAT);
}
#endif
}
/****************************************************************************
* Function: lpc43_interrupt_work
*
* Description:
* Perform interrupt related work from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() was called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc43_interrupt_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
net_lock_t state;
DEBUGASSERT(priv);
/* Process pending Ethernet interrupts */
state = net_lock();
lpc43_interrupt_process(priv);
net_unlock(state);
net_unlock();
/* Re-enable Ethernet interrupts at the NVIC */
up_enable_irq(LPC43M4_IRQ_ETHERNET);
}
#endif
/****************************************************************************
* Function: lpc43_interrupt
@@ -2057,8 +2006,6 @@ static void lpc43_interrupt_work(FAR void *arg)
static int lpc43_interrupt(int irq, FAR void *context)
{
FAR struct lpc43_ethmac_s *priv = &g_lpc43ethmac;
#ifdef CONFIG_NET_NOINTS
uint32_t dmasr;
/* Get the DMA interrupt status bits (no MAC interrupts are expected) */
@@ -2094,49 +2041,9 @@ static int lpc43_interrupt(int irq, FAR void *context)
work_queue(ETHWORK, &priv->work, lpc43_interrupt_work, priv, 0);
}
#else
/* Process the interrupt now */
lpc43_interrupt_process(priv);
#endif
return OK;
}
/****************************************************************************
* Function: lpc43_txtimeout_process
*
* Description:
* Process a TX timeout. Called from the either the watchdog timer
* expiration logic or from the worker thread, depending upon the
* configuration. The timeout means that the last TX never completed.
* Reset the hardware and start again.
*
* Parameters:
* priv - Reference to the driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Global interrupts are disabled by the watchdog logic.
*
****************************************************************************/
static inline void lpc43_txtimeout_process(FAR struct lpc43_ethmac_s *priv)
{
/* Then reset the hardware. Just take the interface down, then back
* up again.
*/
lpc43_ifdown(&priv->dev);
lpc43_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
lpc43_dopoll(priv);
}
/****************************************************************************
* Function: lpc43_txtimeout_work
*
@@ -2154,19 +2061,23 @@ static inline void lpc43_txtimeout_process(FAR struct lpc43_ethmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc43_txtimeout_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
net_lock_t state;
/* Process pending Ethernet interrupts */
/* Then reset the hardware. Just take the interface down, then back
* up again.
*/
state = net_lock();
lpc43_txtimeout_process(priv);
net_unlock(state);
net_lock();
lpc43_ifdown(&priv->dev);
lpc43_ifup(&priv->dev);
/* Then poll the network for new XMIT data */
lpc43_dopoll(priv);
net_unlock();
}
#endif
/****************************************************************************
* Function: lpc43_txtimeout_expiry
@@ -2193,7 +2104,6 @@ static void lpc43_txtimeout_expiry(int argc, uint32_t arg, ...)
ninfo("Timeout!\n");
#ifdef CONFIG_NET_NOINTS
/* Disable further Ethernet interrupts. This will prevent some race
* conditions with interrupt work. There is still a potential race
* condition with interrupt work that is already queued and in progress.
@@ -2212,33 +2122,28 @@ static void lpc43_txtimeout_expiry(int argc, uint32_t arg, ...)
/* Schedule to perform the TX timeout processing on the worker thread. */
work_queue(ETHWORK, &priv->work, lpc43_txtimeout_work, priv, 0);
#else
/* Process the timeout now */
lpc43_txtimeout_process(priv);
#endif
}
/****************************************************************************
* Function: lpc43_poll_process
* Function: lpc43_poll_work
*
* Description:
* Perform the periodic poll. This may be called either from watchdog
* timer logic or from the worker thread, depending upon the configuration.
* Perform periodic polling from the worker thread
*
* Parameters:
* priv - Reference to the driver state structure
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* None
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv)
static void lpc43_poll_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
FAR struct net_driver_s *dev = &priv->dev;
/* Check if the next TX descriptor is owned by the Ethernet DMA or CPU. We
@@ -2252,6 +2157,7 @@ static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv)
* CONFIG_LPC43_ETH_NTXDESC).
*/
net_lock();
if ((priv->txhead->tdes0 & ETH_TDES0_OWN) == 0 &&
priv->txhead->tdes2 == 0)
{
@@ -2287,39 +2193,9 @@ static inline void lpc43_poll_process(FAR struct lpc43_ethmac_s *priv)
/* Setup the watchdog poll timer again */
(void)wd_start(priv->txpoll, LPC43_WDDELAY, lpc43_poll_expiry, 1, priv);
net_unlock();
}
/****************************************************************************
* Function: lpc43_poll_work
*
* Description:
* Perform periodic polling from the worker thread
*
* Parameters:
* arg - The argument passed when work_queue() as called.
*
* Returned Value:
* OK on success
*
* Assumptions:
* Ethernet interrupts are disabled
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc43_poll_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
state = net_lock();
lpc43_poll_process(priv);
net_unlock(state);
}
#endif
/****************************************************************************
* Function: lpc43_poll_expiry
*
@@ -2342,7 +2218,6 @@ static void lpc43_poll_expiry(int argc, uint32_t arg, ...)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions.
*/
@@ -2362,12 +2237,6 @@ static void lpc43_poll_expiry(int argc, uint32_t arg, ...)
(void)wd_start(priv->txpoll, LPC43_WDDELAY, lpc43_poll_expiry, 1,
(uint32_t)priv);
}
#else
/* Process the interrupt now */
lpc43_poll_process(priv);
#endif
}
/****************************************************************************
@@ -2473,37 +2342,6 @@ static int lpc43_ifdown(struct net_driver_s *dev)
return OK;
}
/****************************************************************************
* Function: lpc43_txavail_process
*
* Description:
* Perform an out-of-cycle poll.
*
* Parameters:
* priv - Reference to the NuttX driver state structure
*
* Returned Value:
* None
*
* Assumptions:
* Called in normal user mode
*
****************************************************************************/
static inline void lpc43_txavail_process(FAR struct lpc43_ethmac_s *priv)
{
ninfo("ifup: %d\n", priv->ifup);
/* Ignore the notification if the interface is not yet up */
if (priv->ifup)
{
/* Poll for new XMIT data */
lpc43_dopoll(priv);
}
}
/****************************************************************************
* Function: lpc43_txavail_work
*
@@ -2521,19 +2359,23 @@ static inline void lpc43_txavail_process(FAR struct lpc43_ethmac_s *priv)
*
****************************************************************************/
#ifdef CONFIG_NET_NOINTS
static void lpc43_txavail_work(FAR void *arg)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)arg;
net_lock_t state;
/* Perform the poll */
/* Ignore the notification if the interface is not yet up */
state = net_lock();
lpc43_txavail_process(priv);
net_unlock(state);
net_lock();
ninfo("ifup: %d\n", priv->ifup);
if (priv->ifup)
{
/* Poll for new XMIT data */
lpc43_dopoll(priv);
}
net_unlock();
}
#endif
/****************************************************************************
* Function: lpc43_txavail
@@ -2558,7 +2400,6 @@ static int lpc43_txavail(struct net_driver_s *dev)
{
FAR struct lpc43_ethmac_s *priv = (FAR struct lpc43_ethmac_s *)dev->d_private;
#ifdef CONFIG_NET_NOINTS
/* Is our single work structure available? It may not be if there are
* pending interrupt actions and we will have to ignore the Tx
* availability action.
@@ -2571,21 +2412,6 @@ static int lpc43_txavail(struct net_driver_s *dev)
work_queue(ETHWORK, &priv->work, lpc43_txavail_work, priv, 0);
}
#else
irqstate_t flags;
/* Disable interrupts because this function may be called from interrupt
* level processing.
*/
flags = enter_critical_section();
/* Perform the out-of-cycle poll now */
lpc43_txavail_process(priv);
leave_critical_section(flags);
#endif
return OK;
}
File diff suppressed because it is too large Load Diff
+1
View File
@@ -240,6 +240,7 @@ config ARCH_CHIP_SAM3A
config ARCH_CHIP_SAM4CM
bool
default n
select ARCH_HAVE_MULTICPU
select ARCH_HAVE_TICKLESS
config ARCH_CHIP_SAM4L
+18 -6
View File
@@ -50,13 +50,17 @@ CMN_ASRCS = up_saveusercontext.S up_fullcontextrestore.S up_switchcontext.S
CMN_ASRCS += up_testset.S vfork.S
CMN_CSRCS = up_assert.c up_blocktask.c up_copyfullstate.c up_createstack.c
CMN_CSRCS += up_mdelay.c up_udelay.c up_exit.c up_idle.c up_initialize.c
CMN_CSRCS += up_mdelay.c up_udelay.c up_exit.c up_initialize.c
CMN_CSRCS += up_initialstate.c up_interruptcontext.c up_memfault.c up_modifyreg8.c
CMN_CSRCS += up_modifyreg16.c up_modifyreg32.c up_releasepending.c
CMN_CSRCS += up_releasestack.c up_reprioritizertr.c up_schedulesigaction.c
CMN_CSRCS += up_sigdeliver.c up_stackframe.c up_unblocktask.c up_usestack.c
CMN_CSRCS += up_doirq.c up_hardfault.c up_svcall.c up_vfork.c
ifneq ($(CONFIG_SMP),y)
CMN_CSRCS += up_idle.c
endif
# Configuration-dependent common files
ifeq ($(CONFIG_ARMV7M_CMNVECTOR),y)
@@ -198,14 +202,22 @@ endif
ifeq ($(CONFIG_ARCH_CHIP_SAM4CM),y)
ifeq ($(CONFIG_SAM34_TC),y)
CHIP_CSRCS += sam4cm_tc.c
ifeq ($(CONFIG_SAM34_ONESHOT),y)
CHIP_CSRCS += sam4cm_oneshot.c sam4cm_oneshot_lowerhalf.c
endif
endif # CONFIG_SAM34_ONESHOT
ifeq ($(CONFIG_SAM34_FREERUN),y)
CHIP_CSRCS += sam4cm_freerun.c
endif
endif # CONFIG_SAM34_FREERUN
ifeq ($(CONFIG_SCHED_TICKLESS),y)
CHIP_CSRCS += sam4cm_tickless.c
endif
endif
endif
endif # CONFIG_SCHED_TICKLESS
endif # CONFIG_SAM34_TC
ifeq ($(CONFIG_SMP),y)
CHIP_CSRCS += sam4cm_cpuindex.c sam4cm_cpuidlestack.c
CHIP_CSRCS += sam4cm_cpupause.c sam4cm_cpustart.c sam4cm_idle.c
endif # CONFIG_SMP
endif # CONFIG_ARCH_CHIP_SAM4CM
@@ -65,6 +65,7 @@
/* Internal SRAM memory region */
#define SAM_INTSRAM0_BASE 0x20000000 /* For SAM3U compatibility */
#define SAM_INTSRAM1_BASE 0x20080000 /* 0x20080000-0x200fffff: Internal SRAM 1 */
#define SAM_BBSRAM_BASE 0x22000000 /* 0x22000000-0x23ffffff: 32MB bit-band region */
/* 0x24000000-0x3fffffff: Undefined */
/* Peripherals address region */
+7 -6
View File
@@ -402,10 +402,10 @@
# define PMC_MCKR_CPCSS_SHIFT (16)
# define PMC_MCKR_CPCSS_MASK (0x7 << PMC_MCKR_CPCSS_SHIFT)
# define PMC_MCKR_CPCSS_SLOW (0 << PMC_MCKR_CPCSS_SHIFT) /* Slow Clock */
# define PMC_MCKR_CCPSS_MAIN (1 << PMC_MCKR_CPCSS_SHIFT) /* Main Clock */
# define PMC_MCKR_CCPSS_PLLA (2 << PMC_MCKR_CPCSS_SHIFT) /* PLLA Clock */
# define PMC_MCKR_CCPSS_PLLB (3 << PMC_MCKR_CPCSS_SHIFT) /* PLLB Clock */
# define PMC_MCKR_CCPSS_MCK (4 << PMC_MCKR_CPCSS_SHIFT) /* Master Clock */
# define PMC_MCKR_CPCSS_MAIN (1 << PMC_MCKR_CPCSS_SHIFT) /* Main Clock */
# define PMC_MCKR_CPCSS_PLLA (2 << PMC_MCKR_CPCSS_SHIFT) /* PLLA Clock */
# define PMC_MCKR_CPCSS_PLLB (3 << PMC_MCKR_CPCSS_SHIFT) /* PLLB Clock */
# define PMC_MCKR_CPCSS_MCK (4 << PMC_MCKR_CPCSS_SHIFT) /* Master Clock */
# define PMC_MCKR_CPPRES_SHIFT (20)
# define PMC_MCKR_CPPRES_MASK (0xF << PMC_MCKR_CPPRES_SHIFT)
# define PMC_MCKR_CPPRES(D) (((D) - 1) << PMC_MCKR_CPPRES_SHIFT)
@@ -547,13 +547,14 @@
/* Peripheral Clock Status Register 1 */
#if defined(CONFIG_ARCH_CHIP_SAM3X) || defined(CONFIG_ARCH_CHIP_SAM3X) || \
defined(CONFIG_ARCH_CHIP_SAM4S) || defined(CONFIG_ARCH_CHIP_SAM4E)
defined(CONFIG_ARCH_CHIP_SAM4S) || defined(CONFIG_ARCH_CHIP_SAM4E) || \
defined(CONFIG_ARCH_CHIP_SAM4CM)
# define PMC_PIDH(n) (1 << ((n) - 32))
# define PMC_PID32 (1 << 0) /* Bit 0: PID32 */
# define PMC_PID33 (1 << 1) /* Bit 1: PID33 */
# define PMC_PID34 (1 << 2) /* Bit 2: PID34 */
# if defined(CONFIG_ARCH_CHIP_SAM3X) || defined(CONFIG_ARCH_CHIP_SAM3X) || \
defined(CONFIG_ARCH_CHIP_SAM4E)
defined(CONFIG_ARCH_CHIP_SAM4E) || defined(CONFIG_ARCH_CHIP_SAM4CM)
# define PMC_PID35 (1 << 3) /* Bit 3: PID35 */
# define PMC_PID36 (1 << 4) /* Bit 4: PID36 */
# define PMC_PID37 (1 << 5) /* Bit 5: PID37 */

Some files were not shown because too many files have changed in this diff Show More