Content originally posted in LPCWare by shoeloader on Tue Jun 10 07:41:36 MST 2014 I've written a bootloader for the lpc1788. The bootloader successfully reads an image from a sd-card during startup and loads it in the flash memory when the version, length or crc differs from the image currently in flash. The problem is when I call the user code using a function pointer the microcontroller gets a hardfault error. This is how I store the code in flash: [list] [*]the bootloader is stored in address 0 to 0x5000(sector 0 to 4) [*]meta data about image in flash is stored at address 0x5000(sector 5) [*]user application is only 1440 bytes and blinks an led(no interrupts) and is stored from address 0x6000(sector 6) [*]flash is written in blocks of 4kiB and is padded with zeros so a flash signature can be calculated(this works as well) [*]start and size of flash has been properly entered in keil [/list]
Before I call the user code I disable the systick timer. No other peripherals are enabled. This is how I call the user code:
typedef void (*user_code_pointer_type)(void);
void run_user_code(void){
user_code_pointer_type user_code_entry;
//user_code_entry = (user_code_pointer_type)((uint32_t*)(user_start_sector_address + 4));//causes invstate at 0x6004
user_code_entry = (user_code_pointer_type)(user_start_sector_address|1);//causes impreciserr at 0x6006
//user_code_entry = (user_code_pointer_type)(user_start_sector_address);//causes invstate at 0x6000
//NVIC_SetVTOR(user_start_sector_address);//hardfault handler of user code is called instead
(user_code_entry)();
}
I've tried disabling interrupts, moving interrupt vectors, moving vectors to ram and other things. Nothing works. What am I doing wrong?
Content originally posted in LPCWare by shoeloader on Thu Jun 12 23:40:37 MST 2014 Quote: starblue
UM10470 5.4 Vector table remapping: "The vector table should be located on a 256 word (1024 byte) boundary to insure [sic] alignment on LPC178x/177x family devices." So that had better be
SCB->VTOR = _vector_table_location & 0x3FFFFC00;
The reason is that the LPC178x has more than the minimal number of interrupt sources.
Though that won't help much if the table is not aligned (as the hard fault handler will surely tell you).
Exactly. So that whole mask is pointless(and incorrect as you pointed out).
#if (_vector_table_location)&(1024-1)
#error vector table not properly aligned
#endif
__disable_irq();//no interrupt should be enabled by bootloader, but disable interrupts to be on safe side
SCB->VTOR = _vector_table_location;
__enable_irq();
I rather have a compiler error than a hardfault error.
Content originally posted in LPCWare by starblue on Thu Jun 12 03:18:42 MST 2014 Quote: shoeloader
SCB->VTOR = _vector_table_location & 0x3FFFFF80;
UM10470 5.4 Vector table remapping: "The vector table should be located on a 256 word (1024 byte) boundary to insure [sic] alignment on LPC178x/177x family devices." So that had better be
SCB->VTOR = _vector_table_location & 0x3FFFFC00;
The reason is that the LPC178x has more than the minimal number of interrupt sources.
Though that won't help much if the table is not aligned (as the hard fault handler will surely tell you).
Quote: shoeloader
Now interrupts work. Does anybody know a way to access the IROM1 start value in c-code in keil using a macro? Now I have to use a define a preprocessor symbol myself. How does the linker know where to put startup_LPC177x_8x.s? UV4 creates a linker script (a .sct scatter loading file in their jargon), but it doesn't define symbols for the memory regions, so as far as I can see you'll need to do it yourself.
Content originally posted in LPCWare by shoeloader on Thu Jun 12 02:12:11 MST 2014 Thanks for the tip. The reason I use CMSIS is because we have a lot of code that relies on CMSIS. I will look into LPCOpen.
Content originally posted in LPCWare by shoeloader on Thu Jun 12 01:50:07 MST 2014 Thanks! It works! Now I'm going to see if I can get interrupts to work and run an rtos.
edit: I've cleaned up some of my code. All those magic pointers, magic pointers to pointers and magic offsets have been bypassed:
typedef struct{
uint32_t stack_address; //initial value of stack pointer is stored at top of vector table
void (*reset_address)(void); //reset vector with entry address is located at second 32-bit word
}vector_table_layout;
void run_user_code(void){
vector_table_layout const*const user_vector_table=(vector_table_layout*)user_start_sector_address;
__disable_irq(); //no interrupt should be enabled by bootloader, but disable interrupts to be on safe side
NVIC_SetVTOR(user_start_sector_address); //set vector table offset to user code
__enable_irq();
__set_MSP(user_vector_table->stack_address);//load stackpointer with initial value
(user_vector_table->reset_address)(); //call user code
}
I've found a bug in the CMSIS system_LPC177x_8x.c code of the user code:
#else
//SCB->VTOR = 0x00000000 & 0x3FFFFF80; //loads incorrect address in case user code has an offset
__disable_irq();//no interrupt should be enabled by bootloader, but disable interrupts to be on safe side
SCB->VTOR = _vector_table_location & 0x3FFFFF80;
__enable_irq();
#endif
Now interrupts work. Does anybody know a way to access the IROM1 start value in c-code in keil using a macro? Now I have to use a define a preprocessor symbol myself. How does the linker know where to put startup_LPC177x_8x.s?
off topic: I've never liked CMSIS. It is not high level enough to be flexible and user friendly and you often have to implement extra functions. It is not low level enough, because you can't access all features. CMSIS code compiles with hundreds of warnings. It is very inefficient. Take the pinsel library for instance you won't save a single line of code and it cost you more than 896 bytes of code.
Content originally posted in LPCWare by starblue on Wed Jun 11 06:03:08 MST 2014
user_code_entry = (user_code_pointer_type)((uint32_t*)(user_start_sector_address + 4));//causes invstate at 0x6004
This is wrong. You jump to address 0x6004, instead of the code pointed to by the address at 0x6004. Note this is a difference between ARM Cortex-M and ARM7.
Content originally posted in LPCWare by shoeloader on Wed Jun 11 05:54:40 MST 2014 Thanks for the tip. I tried it but it doesn't work. I now read the initial value of the stack pointer in the user application from the vector table. I've made a stripped down version of the bootloader. I limit the ram size to 1kiB so there is no stack conflict.
#include < stdint.h >
#include "LPC177x_8x.h"
#define user_start_sector_address 0x06000
typedef void (*user_code_pointer_type)(void);
void run_user_code(void){
uint32_t user_stack_pointer;
user_code_pointer_type user_code_entry;
user_code_entry = (user_code_pointer_type)((uint32_t*)(user_start_sector_address + 4));//causes invstate at 0x6004
//user_code_entry = (user_code_pointer_type)(user_start_sector_address|1);//causes impreciserr at 0x6006
//user_code_entry = (user_code_pointer_type)(user_start_sector_address);//causes invstate at 0x6000
//NVIC_SetVTOR(user_start_sector_address);//hardfault handler of user code is called instead
user_stack_pointer=*((uint32_t*)user_start_sector_address);//initial value of stack pointer is stored at top of vector table
__set_MSP(user_stack_pointer);
(user_code_entry)();
}
int main(void){
run_user_code();
while(1);
}
The stack pointer is now initialized with 0x10000670. I still get hardfaults.
Content originally posted in LPCWare by shoeloader on Tue Jun 10 23:38:14 MST 2014 That's why I set bit 0 to 1 by bitwise-OR-ing the address with 1. I've checked it with dissasembly and with the values loaded in the registers. Address 0x6001 is loaded and the code jumps to 0x6000. But at address 0x6006 the microcontroller gets an impreciserr hardfault error. Even stripping the code to just calling user code gives me that error. The reason I tried other address offsets is that NXP uses an offset of 4 in their bootloader examples.
I use keil uvision 4.73 with an Ulink2. Optimization is set to -O1.
Content originally posted in LPCWare by wmues on Tue Jun 10 10:40:27 MST 2014 The Cortex M3 has a THUMB2 command set. To differentiate ARM code from THUMB code, THUMB code has bit 0 of each address set to 1.
Regards
Wolfgang
0
Kudos
Reply
'
var data = div.getElementsByClassName("video-js");
var script = document.createElement('script');
script.src = "https://players.brightcove.net/" + data_account + "/" + data_palyer + "_default/index.min.js";
for(var i=0;i< data.length;i++){
videodata.push(data[i]);
}
}
}
for(var i=0;i< videodata.length;i++){
document.getElementsByClassName('lia-vid-container')[i].innerHTML = videodata[i].outerHTML;
document.body.appendChild(script);
}
}
catch(e){
}
/* Re compile html */
$compile(rootElement.querySelectorAll('div.lia-message-body-content')[0])($scope);
}
if (code_l.toLowerCase() != newBody.getAttribute("slang").toLowerCase()) {
/* Adding Translation flag */
var tr_obj = $filter('filter')($scope.sourceLangList, function (obj_l) {
return obj_l.code.toLowerCase() === newBody.getAttribute("slang").toLowerCase()
});
if (tr_obj.length > 0) {
tr_text = "This content was translated from lilicon-trans-text using AI-assisted tools.".replace(/lilicon-trans-text/g, tr_obj[0].title);
tr_text +='View original';
try {
if ($scope.wootMessages[$rootScope.profLang] != undefined) {
tr_text = $scope.wootMessages[$rootScope.profLang].replace(/lilicon-trans-text/g, tr_obj[0].title);
tr_text +='View original';
}
} catch (e) {
}
} else {
//tr_text = "This message was translated for your convenience!";
tr_text = "lilicon-trans.your.convenience";
}
try {
if (!document.getElementById("tr-msz-" + value)) {
var tr_para = document.createElement("P");
tr_para.setAttribute("id", "tr-msz-" + value);
tr_para.setAttribute("class", "tr-msz");
tr_para.style.textAlign = 'justify';
var tr_fTag = document.createElement("IMG");
tr_fTag.setAttribute("class", "tFlag");
tr_fTag.setAttribute("alt", "Translate icon");
// tr_fTag.setAttribute("title", "Disclaimer for Translate icon");
tr_fTag.setAttribute("src", "/html/assets/translate-icon.svg");
tr_para.appendChild(tr_fTag);
var container = document.createElement('span');
container.innerHTML = tr_text;
//var tr_textNode = document.createTextNode(container);
tr_para.appendChild(container);
/* Woot message only for multi source */
if(rootElement.querySelector(".lia-message-body-content").previousElementSibling != null && rootElement.querySelector(".lia-message-body-content").previousElementSibling.getAttributeNames().includes("data-generation-timestamp")){
rootElement.querySelector(".lia-message-body-content").previousElementSibling.remove()
}
if(rootElement.querySelector(".lia-quilt-forum-message")){
rootElement.querySelector(".lia-quilt-forum-message .lia-message-body").insertBefore(tr_para,rootElement.querySelector(".lia-message-body-content"));
} else if(rootElement.querySelector(".lia-message-view-blog-topic-message")) {
rootElement.querySelector(".lia-message-view-blog-topic-message .lia-message-body").insertBefore(tr_para,rootElement.querySelector(".lia-message-body-content"));
} else if(rootElement.querySelector(".lia-quilt-blog-reply-message")){
rootElement.querySelector(".lia-quilt-blog-reply-message .lia-message-body").insertBefore(tr_para,rootElement.querySelector(".lia-message-body-content"));
} else if(rootElement.querySelector(".lia-quilt-tkb-message")){
rootElement.querySelectorAll(".lia-quilt-tkb-message .lia-message-body")[0].insertBefore(tr_para,rootElement.querySelector(".lia-message-body-content"));
} else if(rootElement.querySelector(".lia-quilt-tkb-reply-message")){
rootElement.querySelectorAll(".lia-quilt-tkb-reply-message .lia-message-body")[0].insertBefore(tr_para,rootElement.querySelector(".lia-message-body-content"));
} else if(rootElement.querySelector(".lia-quilt-idea-message")){
rootElement.querySelector(".lia-quilt-idea-message .lia-message-body").insertBefore(tr_para,rootElement.querySelector(".lia-message-body-content"));
} else if(rootElement.querySelector(".lia-quilt-idea-reply-message")){
rootElement.querySelector(".lia-quilt-idea-reply-message .lia-message-body").insertBefore(tr_para,rootElement.querySelector(".lia-message-body-content"));
} else if(rootElement.querySelector('.lia-quilt-occasion-message')){
rootElement.querySelector('.lia-quilt-occasion-message .lia-message-body').insertBefore(tr_para,rootElement.querySelector(".lia-message-body-content"));
}
else {
if (rootElement.querySelectorAll('div.lia-quilt-row-footer').length > 0) {
rootElement.querySelectorAll('div.lia-quilt-row-footer')[0].appendChild(tr_para);
} else {
rootElement.querySelectorAll('div.lia-quilt-column-message-footer')[0].appendChild(tr_para);
}
}
}
} catch (e) {
}
}
} else {
/* Do not display button for same language */
// syncList.remove(value);
var index = $scope.syncList.indexOf(value);
if (index > -1) {
$scope.syncList.splice(index, 1);
}
}
}
}
}
}
/*if(mszList_l.length <= 0){
setTimeout(()=>{
var mszListl = [];
angular.forEach(document.querySelectorAll("[class*='lia-js-data-messageUid']"), function(element) {
var mszId = element.getAttribute("data-lia-message-uid");
if (mszId != null) {
mszListl.push(mszId);
}
});
var mszListid = mszListl;
console.log("mszListl:",mszListl);
},2000)
}else{
var mszListid = mszList_l;
}*/
console.log("mszList_l:",mszList_l.length);
angular.forEach(mszList_l, function (value) {
if (document.querySelectorAll('div.lia-js-data-messageUid-' + value).length > 0) {
var rootElements = document.querySelectorAll('div.lia-js-data-messageUid-' + value);
}else if(document.querySelectorAll('.lia-occasion-message-view .lia-component-occasion-message-view').length >0){
var rootElements = document.querySelectorAll('.lia-occasion-message-view .lia-component-occasion-message-view')[0].querySelectorAll('.lia-occasion-description')[0];
}else {
var rootElements = document.querySelectorAll('div.message-uid-' + value);
}
angular.forEach(rootElements, function (rootElement) {
if (value == '523435' && "ForumTopicPage" == "TkbArticlePage") {
rootElement = document.querySelector('.lia-thread-topic');
}
/* V1.1 Remove from UI */
if (document.getElementById("tr-msz-" + value)) {
document.getElementById("tr-msz-" + value).remove();
}
if (document.getElementById("tr-sync-" + value)) {
document.getElementById("tr-sync-" + value).remove();
}
/* XPath expression for subject and Body */
var lingoRBExp = "//lingo-body[@id = "+"'lingo-body-"+value+"'"+"]";
lingoRSExp = "//lingo-sub[@id = "+"'lingo-sub-"+value+"'"+"]";
/* Get translated subject of the message */
lingoRSXML = doc.evaluate(lingoRSExp, doc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
for(var i=0;i 0){
angular.forEach(document.querySelectorAll(".PageTitle"), function(subEle) {
subEle.textContent = sub_L;
});
}
}
}
// Label translation
try{
var labelEle = document.querySelector("#labelsForMessage");
if(!labelEle){
labelEle = document.querySelector(".LabelsList");
}
if(labelEle) {
var listContains = labelEle.querySelector('.label');
if (listContains) {
/* Commenting this code as bussiness want to point search with source language label */
// var tagHLink = labelEle.querySelectorAll(".label")[0].querySelector(".label-link").href.split("label-name")[0];
var lingoLabelExp = "//lingo-label/text()";
trLabels = [];
trLabelsHtml = "";
/* Get translated labels of the message */
lingoLXML = doc.evaluate(lingoLabelExp, doc, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null);
var labelsLength = document.querySelector(".LabelsList").querySelectorAll(".label").length;
var labelSnapshotLength = lingoLXML.snapshotLength;
if (labelsLength == labelSnapshotLength){
for (var k = 0; k < lingoLXML.snapshotLength; k++) {
//trLabels.push(lingoLXML.snapshotItem(i).textContent);
if (k != 0) {
//trLabelsHtml = trLabelsHtml + '