Skip to content
Snippets Groups Projects
Commit d064a263 authored by iliya's avatar iliya
Browse files

initial file structure

parents
No related branches found
No related tags found
No related merge requests found
.section .text,"ax"
.cpu cortex-m3
.thumb
.syntax unified
#include "globals.h"
.global asm_test_fault
.global switch_to_user_mode
.extern user_stack DATA // this adress can be read like: ldr Rx, =user_stack
switch_to_user_mode:
bx lr
.equ bad_addr,0x90000
.thumb_func
asm_test_fault:
ldr r0,=bad_addr
ldr r1,[r0] // mem access error
mov r2,#2
mov r3,#3
nop
bx lr
.ltorg
//*****************************************************************************
// LPC175x_6x Microcontroller Startup code for use with LPCXpresso IDE
//
// Version : 150706
//*****************************************************************************
//
// Copyright(C) NXP Semiconductors, 2014-2015
// All rights reserved.
//
// Software that is described herein is for illustrative purposes only
// which provides customers with programming information regarding the
// LPC products. This software is supplied "AS IS" without any warranties of
// any kind, and NXP Semiconductors and its licensor disclaim any and
// all warranties, express or implied, including all implied warranties of
// merchantability, fitness for a particular purpose and non-infringement of
// intellectual property rights. NXP Semiconductors assumes no responsibility
// or liability for the use of the software, conveys no license or rights under any
// patent, copyright, mask work right, or any other intellectual property rights in
// or to any products. NXP Semiconductors reserves the right to make changes
// in the software without notification. NXP Semiconductors also makes no
// representation or warranty that such application will be suitable for the
// specified use without further testing or modification.
//
// Permission to use, copy, modify, and distribute this software and its
// documentation is hereby granted, under NXP Semiconductors' and its
// licensor's relevant copyrights in the software, without fee, provided that it
// is used in conjunction with NXP Semiconductors microcontrollers. This
// copyright, permission, and disclaimer notice must appear in all copies of
// this code.
//*****************************************************************************
#if defined (__cplusplus)
#ifdef __REDLIB__
#error Redlib does not support C++
#else
//*****************************************************************************
//
// The entry point for the C++ library startup
//
//*****************************************************************************
extern "C" {
extern void __libc_init_array(void);
}
#endif
#endif
#define WEAK __attribute__ ((weak))
#define ALIAS(f) __attribute__ ((weak, alias (#f)))
//*****************************************************************************
#if defined (__cplusplus)
extern "C" {
#endif
//*****************************************************************************
#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN)
// Declaration of external SystemInit function
extern void SystemInit(void);
#endif
//*****************************************************************************
//
// Forward declaration of the default handlers. These are aliased.
// When the application defines a handler (with the same name), this will
// automatically take precedence over these weak definitions
//
//*****************************************************************************
void ResetISR(void);
WEAK void NMI_Handler(void);
WEAK void HardFault_Handler(void);
WEAK void MemManage_Handler(void);
WEAK void BusFault_Handler(void);
WEAK void UsageFault_Handler(void);
WEAK void SVC_Handler(void);
WEAK void DebugMon_Handler(void);
WEAK void PendSV_Handler(void);
WEAK void SysTick_Handler(void);
WEAK void IntDefaultHandler(void);
//*****************************************************************************
//
// Forward declaration of the specific IRQ handlers. These are aliased
// to the IntDefaultHandler, which is a 'forever' loop. When the application
// defines a handler (with the same name), this will automatically take
// precedence over these weak definitions
//
//*****************************************************************************
void WDT_IRQHandler(void) ALIAS(IntDefaultHandler);
void TIMER0_IRQHandler(void) ALIAS(IntDefaultHandler);
void TIMER1_IRQHandler(void) ALIAS(IntDefaultHandler);
void TIMER2_IRQHandler(void) ALIAS(IntDefaultHandler);
void TIMER3_IRQHandler(void) ALIAS(IntDefaultHandler);
void UART0_IRQHandler(void) ALIAS(IntDefaultHandler);
void UART1_IRQHandler(void) ALIAS(IntDefaultHandler);
void UART2_IRQHandler(void) ALIAS(IntDefaultHandler);
void UART3_IRQHandler(void) ALIAS(IntDefaultHandler);
void PWM1_IRQHandler(void) ALIAS(IntDefaultHandler);
void I2C0_IRQHandler(void) ALIAS(IntDefaultHandler);
void I2C1_IRQHandler(void) ALIAS(IntDefaultHandler);
void I2C2_IRQHandler(void) ALIAS(IntDefaultHandler);
void SPI_IRQHandler(void) ALIAS(IntDefaultHandler);
void SSP0_IRQHandler(void) ALIAS(IntDefaultHandler);
void SSP1_IRQHandler(void) ALIAS(IntDefaultHandler);
void PLL0_IRQHandler(void) ALIAS(IntDefaultHandler);
void RTC_IRQHandler(void) ALIAS(IntDefaultHandler);
void EINT0_IRQHandler(void) ALIAS(IntDefaultHandler);
void EINT1_IRQHandler(void) ALIAS(IntDefaultHandler);
void EINT2_IRQHandler(void) ALIAS(IntDefaultHandler);
void EINT3_IRQHandler(void) ALIAS(IntDefaultHandler);
void ADC_IRQHandler(void) ALIAS(IntDefaultHandler);
void BOD_IRQHandler(void) ALIAS(IntDefaultHandler);
void USB_IRQHandler(void) ALIAS(IntDefaultHandler);
void CAN_IRQHandler(void) ALIAS(IntDefaultHandler);
void DMA_IRQHandler(void) ALIAS(IntDefaultHandler);
void I2S_IRQHandler(void) ALIAS(IntDefaultHandler);
#if defined (__USE_LPCOPEN)
void ETH_IRQHandler(void) ALIAS(IntDefaultHandler);
#else
void ENET_IRQHandler(void) ALIAS(IntDefaultHandler);
#endif
void RIT_IRQHandler(void) ALIAS(IntDefaultHandler);
void MCPWM_IRQHandler(void) ALIAS(IntDefaultHandler);
void QEI_IRQHandler(void) ALIAS(IntDefaultHandler);
void PLL1_IRQHandler(void) ALIAS(IntDefaultHandler);
void USBActivity_IRQHandler(void) ALIAS(IntDefaultHandler);
void CANActivity_IRQHandler(void) ALIAS(IntDefaultHandler);
//*****************************************************************************
//
// The entry point for the application.
// __main() is the entry point for Redlib based applications
// main() is the entry point for Newlib based applications
//
//*****************************************************************************
#if defined (__REDLIB__)
extern void __main(void);
#endif
extern int main(void);
//*****************************************************************************
//
// External declaration for the pointer to the stack top from the Linker Script
//
//*****************************************************************************
extern void _vStackTop(void);
//*****************************************************************************
//
// External declaration for LPC MCU vector table checksum from Linker Script
//
//*****************************************************************************
WEAK extern void __valid_user_code_checksum();
//*****************************************************************************
#if defined (__cplusplus)
} // extern "C"
#endif
//*****************************************************************************
//
// The vector table.
// This relies on the linker script to place at correct location in memory.
//
//*****************************************************************************
extern void (* const g_pfnVectors[])(void);
__attribute__ ((used,section(".isr_vector")))
void (* const g_pfnVectors[])(void) = {
// Core Level - CM3
&_vStackTop, // The initial stack pointer
ResetISR, // The reset handler
NMI_Handler, // The NMI handler
HardFault_Handler, // The hard fault handler
MemManage_Handler, // The MPU fault handler
BusFault_Handler, // The bus fault handler
UsageFault_Handler, // The usage fault handler
__valid_user_code_checksum, // LPC MCU Checksum
0, // Reserved
0, // Reserved
0, // Reserved
SVC_Handler, // SVCall handler
DebugMon_Handler, // Debug monitor handler
0, // Reserved
PendSV_Handler, // The PendSV handler
SysTick_Handler, // The SysTick handler
// Chip Level - LPC17
WDT_IRQHandler, // 16, 0x40 - WDT
TIMER0_IRQHandler, // 17, 0x44 - TIMER0
TIMER1_IRQHandler, // 18, 0x48 - TIMER1
TIMER2_IRQHandler, // 19, 0x4c - TIMER2
TIMER3_IRQHandler, // 20, 0x50 - TIMER3
UART0_IRQHandler, // 21, 0x54 - UART0
UART1_IRQHandler, // 22, 0x58 - UART1
UART2_IRQHandler, // 23, 0x5c - UART2
UART3_IRQHandler, // 24, 0x60 - UART3
PWM1_IRQHandler, // 25, 0x64 - PWM1
I2C0_IRQHandler, // 26, 0x68 - I2C0
I2C1_IRQHandler, // 27, 0x6c - I2C1
I2C2_IRQHandler, // 28, 0x70 - I2C2
SPI_IRQHandler, // 29, 0x74 - SPI
SSP0_IRQHandler, // 30, 0x78 - SSP0
SSP1_IRQHandler, // 31, 0x7c - SSP1
PLL0_IRQHandler, // 32, 0x80 - PLL0 (Main PLL)
RTC_IRQHandler, // 33, 0x84 - RTC
EINT0_IRQHandler, // 34, 0x88 - EINT0
EINT1_IRQHandler, // 35, 0x8c - EINT1
EINT2_IRQHandler, // 36, 0x90 - EINT2
EINT3_IRQHandler, // 37, 0x94 - EINT3
ADC_IRQHandler, // 38, 0x98 - ADC
BOD_IRQHandler, // 39, 0x9c - BOD
USB_IRQHandler, // 40, 0xA0 - USB
CAN_IRQHandler, // 41, 0xa4 - CAN
DMA_IRQHandler, // 42, 0xa8 - GP DMA
I2S_IRQHandler, // 43, 0xac - I2S
#if defined (__USE_LPCOPEN)
ETH_IRQHandler, // 44, 0xb0 - Ethernet
#else
ENET_IRQHandler, // 44, 0xb0 - Ethernet
#endif
RIT_IRQHandler, // 45, 0xb4 - RITINT
MCPWM_IRQHandler, // 46, 0xb8 - Motor Control PWM
QEI_IRQHandler, // 47, 0xbc - Quadrature Encoder
PLL1_IRQHandler, // 48, 0xc0 - PLL1 (USB PLL)
USBActivity_IRQHandler, // 49, 0xc4 - USB Activity interrupt to wakeup
CANActivity_IRQHandler, // 50, 0xc8 - CAN Activity interrupt to wakeup
};
//*****************************************************************************
// Functions to carry out the initialization of RW and BSS data sections. These
// are written as separate functions rather than being inlined within the
// ResetISR() function in order to cope with MCUs with multiple banks of
// memory.
//*****************************************************************************
__attribute__ ((section(".after_vectors")))
void data_init(unsigned int romstart, unsigned int start, unsigned int len) {
unsigned int *pulDest = (unsigned int*) start;
unsigned int *pulSrc = (unsigned int*) romstart;
unsigned int loop;
for (loop = 0; loop < len; loop = loop + 4)
*pulDest++ = *pulSrc++;
}
__attribute__ ((section(".after_vectors")))
void bss_init(unsigned int start, unsigned int len) {
unsigned int *pulDest = (unsigned int*) start;
unsigned int loop;
for (loop = 0; loop < len; loop = loop + 4)
*pulDest++ = 0;
}
//*****************************************************************************
// The following symbols are constructs generated by the linker, indicating
// the location of various points in the "Global Section Table". This table is
// created by the linker via the Code Red managed linker script mechanism. It
// contains the load address, execution address and length of each RW data
// section and the execution and length of each BSS (zero initialized) section.
//*****************************************************************************
extern unsigned int __data_section_table;
extern unsigned int __data_section_table_end;
extern unsigned int __bss_section_table;
extern unsigned int __bss_section_table_end;
//*****************************************************************************
// Reset entry point for your code.
// Sets up a simple runtime environment and initializes the C/C++
// library.
//*****************************************************************************
__attribute__ ((section(".after_vectors")))
void
ResetISR(void) {
//
// Copy the data sections from flash to SRAM.
//
unsigned int LoadAddr, ExeAddr, SectionLen;
unsigned int *SectionTableAddr;
// Load base address of Global Section Table
SectionTableAddr = &__data_section_table;
// Copy the data sections from flash to SRAM.
while (SectionTableAddr < &__data_section_table_end) {
LoadAddr = *SectionTableAddr++;
ExeAddr = *SectionTableAddr++;
SectionLen = *SectionTableAddr++;
data_init(LoadAddr, ExeAddr, SectionLen);
}
// At this point, SectionTableAddr = &__bss_section_table;
// Zero fill the bss segment
while (SectionTableAddr < &__bss_section_table_end) {
ExeAddr = *SectionTableAddr++;
SectionLen = *SectionTableAddr++;
bss_init(ExeAddr, SectionLen);
}
#if defined (__USE_CMSIS) || defined (__USE_LPCOPEN)
SystemInit();
#endif
#if defined (__cplusplus)
//
// Call C++ library initialisation
//
__libc_init_array();
#endif
#if defined (__REDLIB__)
// Call the Redlib library, which in turn calls main()
__main() ;
#else
main();
#endif
//
// main() shouldn't return, but if it does, we'll just enter an infinite loop
//
while (1) {
;
}
}
//*****************************************************************************
// Default exception handlers. Override the ones here by defining your own
// handler routines in your application code.
//*****************************************************************************
__attribute__ ((section(".after_vectors")))
void NMI_Handler(void)
{ while(1) {}
}
__attribute__ ((section(".after_vectors")))
void HardFault_Handler(void)
{ while(1) {}
}
__attribute__ ((section(".after_vectors")))
void MemManage_Handler(void)
{ while(1) {}
}
__attribute__ ((section(".after_vectors")))
void BusFault_Handler(void)
{ while(1) {}
}
__attribute__ ((section(".after_vectors")))
void UsageFault_Handler(void)
{ while(1) {}
}
__attribute__ ((section(".after_vectors")))
void SVC_Handler(void)
{ while(1) {}
}
__attribute__ ((section(".after_vectors")))
void DebugMon_Handler(void)
{ while(1) {}
}
__attribute__ ((section(".after_vectors")))
void PendSV_Handler(void)
{ while(1) {}
}
__attribute__ ((section(".after_vectors")))
void SysTick_Handler(void)
{ while(1) {}
}
//*****************************************************************************
//
// Processor ends up here if an unexpected interrupt occurs or a specific
// handler is not present in the application code.
//
//*****************************************************************************
__attribute__ ((section(".after_vectors")))
void IntDefaultHandler(void)
{ while(1) {}
}
crp.c 0 → 100644
//*****************************************************************************
// crp.c
//
// Source file to create CRP word expected by LPCXpresso IDE linker
//*****************************************************************************
//
// Copyright(C) NXP Semiconductors, 2013
// All rights reserved.
//
// Software that is described herein is for illustrative purposes only
// which provides customers with programming information regarding the
// LPC products. This software is supplied "AS IS" without any warranties of
// any kind, and NXP Semiconductors and its licensor disclaim any and
// all warranties, express or implied, including all implied warranties of
// merchantability, fitness for a particular purpose and non-infringement of
// intellectual property rights. NXP Semiconductors assumes no responsibility
// or liability for the use of the software, conveys no license or rights under any
// patent, copyright, mask work right, or any other intellectual property rights in
// or to any products. NXP Semiconductors reserves the right to make changes
// in the software without notification. NXP Semiconductors also makes no
// representation or warranty that such application will be suitable for the
// specified use without further testing or modification.
//
// Permission to use, copy, modify, and distribute this software and its
// documentation is hereby granted, under NXP Semiconductors' and its
// licensor's relevant copyrights in the software, without fee, provided that it
// is used in conjunction with NXP Semiconductors microcontrollers. This
// copyright, permission, and disclaimer notice must appear in all copies of
// this code.
//*****************************************************************************
#if defined (__CODE_RED)
#include <NXP/crp.h>
// Variable to store CRP value in. Will be placed automatically
// by the linker when "Enable Code Read Protect" selected.
// See crp.h header for more information
__CRP const unsigned int CRP_WORD = CRP_NO_CRP ;
#endif
/*
* globals.h
*
* Created on: 16 nov. 2023
* Author: Vincent
*/
#ifndef GLOBALS_H_
#define GLOBALS_H_
#define USER_STACK_SIZE 0x800
#endif /* GLOBALS_H_ */
/*******************************************************************************************************************
Name : labo_mpu_user_console.c
Author : VP
Date : 11.2023
Description : template file
Notes:
- writing to control register has no effect in user mode!
- the UART must be accessible in both user and supervisor mode
- the timers (and other peripherals) are accessible only in supervisor mode (TCR0:0x40004004, TC0:0x40004008)
********************************************************************************************************************/
#ifdef __USE_CMSIS
#include "LPC17xx.h"
#endif
#include <cr_section_macros.h>
#include <stdbool.h>
#include <stdio.h>
#include "globals.h"
#include "user_cmd.h"
#include "uart.h"
#define MMFAR *(unsigned *)0xE000ED34
unsigned user_stack[USER_STACK_SIZE]; // space for user stack
void *user_stating_address;
int *p_sram2 = (int*) 0x2007c000, a, *p_out_of_mem = (int*) 0x80000;
void switch_to_user_mode();
void asm_test_fault();
void MemManage_Handler() {
SCB->SHCSR |= (1 << 16);
// Activez le MPU
}
void test_supervisor_mode() {
a = *p_sram2; // OK
*p_sram2 = 5; // OK (write in privileged mode)
LPC_GPIO2->FIOPIN = 0xaa; // OK
asm_test_fault(); // not OK
a = *p_out_of_mem; // not OK (out of regions)
}
void test_user_mode() {
int n;
for (n = 0; n < 3; n++)
; // OK
LPC_GPIO2->FIOPIN = 0xaa; // not OK (read only)
a = LPC_GPIO2->FIOPIN; // OK
a = *p_sram2; // OK (unprivileged read only)
*p_sram2 = 5; // not OK (privileged only for writing)
n = LPC_TIM0->TC; // not OK (privileged access only)
}
int main(void) {
// MPU configuration here...
// testing memory accesses in supervisor mode:
test_supervisor_mode(); // to be removed after checking
user_start: user_stating_address = &&user_start;// save the address of the label 'user_start' (for exercise 2)
switch_to_user_mode(); // to be implemented
// testing memory accesses in user mode:
test_user_mode(); // to be removed after checking
while (1) {
exec_user_read_write();
}
return 0;
}
uart.h 0 → 100644
/*
* Description: UART 0 driver
* Created on : 30 sept. 2013
* Author : VP
*/
#ifndef __UART_H
#define __UART_H
#include <stdint.h>
#define IER_RX 0x1 // interrupt enable flags
#define IER_TX 0x2
#define IIR_TX 0x2 // interrupt identification flags
#define IIR_RX 0x4
#define IS_TX_EMPTY (1<<5) // status flags on LSR register
#define IS_RX_NOT_EMPTY (1<<0)
/* Callback function prototype for UART interrupt */
typedef void (*uart_callback_t)(int int_status);
/* Description: UART 0 initialisation. Callbacks can be used, but at most once for TX and once for RX data.
* Note that only the first call of uart0_init_ref is setting up the baudrate, which can't be
* modified during further calls.
*
* Parameters: baudrate [bit/s]
* tx_callback: pointer on callback function called by interrupt at the end of TX character
* transmission. Note that calling uart0_init_ref() does NOT activate IER_THRE to avoid
* continuous calls of tx_callback when the transmission buffer is empty. It is up to
* the user to enable it when necessary (LPC_UART0->IER |= IER_THRE) and to disable it at
* the end of the transmission (LPC_UART0->IER &= ~IER_THRE). Once IER configured to enable
* the interrupt, the first interrupt can be provoked either by sending a character on the UART
* or by forcing the VIC to rise it with NVIC_SetPendingIRQ(UART0_IRQn). Note that if this last
* method is used, the int_flags of the callback parameter are not significant. In this case,
* LPC_UART0->LSR must be read to know if a transmission has been done.
* rx_callback: pointer on callback function called by interrupt on RX character
* receiving. if NULL is given, no interrupt is configured. The callback
* will be called each time a character is received.
*/
void uart0_init_ref(uint32_t baudrate, uart_callback_t tx_callback, uart_callback_t rx_callback);
/* Description: UART 0 initialisation
*
* Parameters: data: pointer on data to be sent
* length: data length [bytes]
*/
void uart0_send_ref(uint8_t *data, uint32_t length);
/* Description: Block until receiving one byte (polling)
* Return: byte read */
char uart0_rec_byte_ref();
/* Description: stop UART0 interrupts. The switch off is only managed by the VIC. */
void uart0_stop_interrupt();
#endif
/*
* user_interpreter.c
*
* Created on: 12 nov. 2023
* Author: Vincent
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <stdarg.h>
#include "uart.h"
#include "user_cmd.h"
#define PRINT_SYNTAX_ERROR() PRINT("Syntax error! Expected syntax is either <8 characters hexadecimal address> for reading\n or " \
"<8 characters hexadecimal address>=<8 characters hexadecimal value> for writing\n");
bool is_supervisor_mode=false;
void SVC_Handler()
{
// to be filled for exercise 4
}
void exec_user_read_write()
{
char str[200];
int i=0, coma_nb=0, value_idx;
unsigned addr, value;
PRINT("Write an hexadecimal address for reading <addr> or <addr>,<value> for writing (%s):\n", is_supervisor_mode?"Supervisor":"User");
fflush(stdin);
fscanf(stdin, "%s",str);
for (i=0; i<strlen(str); i++)
{
if (str[i] == ',')
{
if (i==0 || ++coma_nb>1)
{
PRINT_SYNTAX_ERROR();
return;
}
str[i]=0;
value_idx=i+1;
} else if (!isxdigit(str[i]))
{
PRINT_SYNTAX_ERROR();
return;
}
}
if ((coma_nb&(i<2)) || i>17)
{
PRINT_SYNTAX_ERROR();
PRINT("(Bad length!)");
return;
}
sscanf(str, "%x", &addr);
if (!coma_nb) // if read
{
PRINT("reading address: 0x%08x\n", addr);
PRINT("value read: 0x%08x\n", *(unsigned *)addr);
}
else // write
{
sscanf(str+value_idx, "%x", &value);
PRINT("writing address: 0x%08x with 0x%08x\n", addr, value);
*(unsigned *)addr=value;
}
}
/*
* user_cmd.h
*
* Created on: 12 nov. 2023
* Author: VP
*/
#ifndef USER_CMD_H_
#define USER_CMD_H_
#define UART_ENABLE 0 // if 0, the console is MCUXpresso, otherwise the UART (use a terminal on PC side)
#if !UART_ENABLE
#define PRINT printf
#endif
void exec_user_read_write();
#endif /* USER_CMD_H_ */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment