Embarrassing to say, but just like any other technical documentation, there are a few errors in my books . Over the years I have learn a lot from my mistakes, but it is still impossible to catch all of the errors before the books are printed. In this document I summaries the errors I am aware of. This document will be updated from time to time as and when issues are found.
Hope you enjoy the books.
regards,
Joseph
Note: The page numbers are referring to the pages on paper copies.
The Definitive Guide to ARM Cortex-M3 and Cortex-M4 Processors, 3rd edition
Page | Descriptions |
---|---|
83 | Typo at middle of page ("ERSR" should be "EPSR"): The EPSR cannot be accessed by software code directly using MRS (read as zero) or MSR |
100 | Figure 4.20, the order of POP instructions should be inverted of the order in PUSH. The corrected diagram is shown below: |
132 | MVN description: Should be "Move NOT" rather than "Move negative" |
136 | In the third paragraph in page 136 it should be "If the floating point unit is present, the instructions in Table 5.10 are also available to perform LDR and STR operations to the registers in the floating point unit." |
218 to 219 | Section 6.9 Memory access attributes Last sentence in page 218 should be "The Cacheable and Bufferable attributes are usually used by a cache controller, which specifies memory types and caching scheme, as shown in Table 6.11." |
265 | 7.10.1 PRIMASK Typo near middle of the page: "PRIMARK" should be "PRIMASK" "In assembly language programming, you can change the value of PRIMASK register using CPS (Change Processor State) instructions:" |
335 | In example code B __cpp(SVC_Handler_C) should have been B __cpp(SVC_Handler_main) |
335 | SVC with priority escalation lead to HardFault, not Usage Fault. "Because of the exception priority model, you cannot use SVC inside an SVC handler (because the priority us the same as the current priority). Doing so will result in a HardFault exception. For the same reason, you cannot use SVC in the NMI handler or the HardFault handler." |
372 | In C example, function "mpu_enable(uint32_t options)", there is a typo in the comment void mpu_enable(uint32_t options) { MPU->CTRL = MPU_CTRL_ENABLE_Msk j options; // Enable the MPU __DSB(); // Ensure MPU settings take effects __ISB(); // Sequence instruction fetches using update settings return; } |
384 | The Usage Fault exception can be caused by a wide range of factors: "Execution of SVC when the priority Level of the SVC is the same or lower than current Level " this scenario lead to a HardFault not a Usage Fault. |
389 | Section 12.4.5, first sentence should be: "The programmer's model for the HardFault Status Register is shown in Table 12.6." |
425 | Section 13.2.8, typo in 2nd paragraph: FPFSCR should be FPDSCR. |
754 | Example for re-entrant interrupt handler. Two addition steps might be needed 1) to prevent a new re-entrant interrupt being triggered just before execution of SVC (I am still doing more check in this). To avoid the potential issue, set BASEPRI to the same level as the re-entrant interrupt (e.g. SysTick in this case) before SVC and clear BASEPRI inside the SVC Handler: 2) for Cortex-M4 with FPU, also need to trigger the deferred lazy stacking __asm void SysTick_Handler(void) { #if (__CORTEX_M >= 0x04) #if (__FPU_USED == 1) ; The following 3 lines are for Cortex-M4 with FPU only TST LR, #0x10 ; Test bit 4, if zero, need to trigger stacking IT EQ VMOVEQ.F32 S0, S0 ; Trigger lazy stacking stacking #endif #endif ; Now we are in Handler mode, using Main Stack, and ; SP should be Double word aligned MRS R0, PSR PUSH {R0, LR} ; Need to save PSR and LR in stack ... SysTick_Handler_thread_pt BL __cpp(Reentrant_SysTick_Handler) ; Block SysTick from being triggered just before SVC LDR R0,=0xE000ED23 ; Address of SysTick priority level LDR R0,[R0] MSR BASEPRI, R0 ; Block SysTick from being triggered ISB ; Instruction Synchronisation Barrier
SVC 0 ; Use SVC to return to original Thread B . ; Should not return here __asm void SVC_Handler(void) { MOVS R0, #0 MSR BASEPRI, R0 ; Enable SysTick again ISB ; Instruction Synchronisation Barrier #if (__CORTEX_M >= 0x04) #if (__FPU_USED == 1) ; The following 3 lines are for Cortex-M4 with FPU only TST LR, #0x10 ; Test bit 4, if zero, need to trigger stacking IT EQ VMOVEQ.F32 S0, S0 ; Trigger lazy stacking stacking #endif #endif ; Extract SVC number TST LR, #0x4 ; Test EXC_RETURN bit 2 ITE EQ ; if ... Please also note that the current code can only work if the re-entrant interrupt has the lowest priority compared to other interrupt sources. |
Note: Due to the size of the book, the publisher had decided to remove the appendix in paper copies and put it on the web. This is now available for download on the Elsevier's website: http://booksite.elsevier.com/9780124080829/
The Definitive Guide to the ARM Cortex-M3, 2nd edition
Page | Descriptions |
---|---|
29 (3.2.1) | Example for MRS and MSR: EPSR cannot be read. So you can only get 0 when executing "MRS r0, EPSR" |
49 (table 4.6), 53 | MVN description: Should be "Move NOT" rather than "Move negative" |
59 | Table 4.21 text alignment issues: "ASRRd, Rn" should be "ASR Rd, Rn" "LSLRd, #immed" should be "LSL Rd, #immed" "LSLRd, Rn" should be "LSL Rd, Rn" |
107 | "Internet Protocol providers" should be "IP (Intellectual Property) providers" (I blame the editor for this one ) |
142 | Table 8.12 SYSTICK Calibration Value Register TENMS field should be RO (read only), not R/W (read/write) |
178 | Example code (int LockDeviceA(void)): if (__LDREXW(&DeviceALocked) = 0) { Should be if (__LDREXW(&DeviceALocked) == 0) { |
205 | Example code for non-base thread enable need to be updated to handle double word stack alignment correctly (see example code for the new Cortex-M3/M4 book). |
249 | Table 15.1, C_HALT bit is reset by system reset, not power on reset. |
250 | Foot note for table 15.2 "The control bit in DHCSR..." should be "The control bit in DEMCR..." |
262 | First paragraph: "Text Data Output (TDO)" should be "Test Data Output (TDO)". |
281 | Figure 17.5 "0.9 DMIP/MHz" should be "0.9 DMIPS/MHz" |
305 | Section 19.6 Using unsupported instructions ".word" should be changed to ".inst" |
355 | The following description of carry bit is incorrect: "A carry occurs • If the result of an addition is greater than or equal to 2^32 • If the result of a subtraction is positive or zero • As the result of an inline barrel shifter operation in a move or logical instruction."
The correct description is: "C is set in one of four ways:
(Note: this error originated from ARM documentation - a defect has been raised) |
410 | Table D.6 SYSTICK Calibration Value Register TENMS field should be RO (read only), not R/W (read/write) |
415 | Table D.23 Usage Fault Status Register UNALIGNED bit description. The text said it can only be set if UNALIGN_TRP is set. This is incorrect. It can be set if an unaligned transfer is attempted for instructions that doesn't support unaligned transfers (e.g. LDMIA/STMIA). |
428 | Table E.6: DEBUGEVF should be DEBUGEVT |
The Definitive Guide to the ARM Cortex-M3, 1st edition
Most of the most issues found are documented here. Please so see the errors in the second edition.
The Definitive Guide to the ARM Cortex-M0, 1st edition
(to be added)
Page | Descriptions |
---|---|
4 | In figure 1.1 for processor IP there's a typo of Mail instead of Mali |
30 | Typo in equations: // Calculating Z = X + Y, where X, Y and Z are all 64-bit Z[31:0] = X[31:0] + Y[31:0]; // Calculate lower word addition, carry flag get updated Z[63:32] = X[63:32] + Y[63:32] + Carry; // Calculate upper word addition |
78 | Table 5.3 : In GNU Assembler, instruction should be delared using .inst rather than .word |
87 | Notes for PUSH instructions incorrectly described register layout ordering. For PUSH {<Ra>, <Rb>,...} instruction: SP is first updated to new SP value, and then: memory[new_SP ] = Ra, memory[new_SP+4] = Rb, ... (The order of the register content is based on register's number, i.e. Lower register is push to the lower address in the stack). |
121 | Figure 6.8 - On page 121 in figure 6.8 "simple unsigned integer square root function" the diagram shows that when the check for "N = 0" fails the flow returns to "M = 0" which is incorrect. The program flow should loop around to the step labelled "M = M + N". (Thanks Brendan M for pointing this out). |
170 | Figure 9.4 : Wrong diagram - It is duplicated from figure 9.3. The correct image should be: Figure 9.4 : Interrupt pending status is cleared and is not taken by the processor. |
186 | At the bottom of the page, the last statement is incorrect. The correct descriptions should be: "The SysTick Calibrate Value Register can be used to provide information for calculating the desired reload value for the SysTick. If a timing reference is available on the microcontroller, the TENMS field in the register may provide the tick count for 10 milliseconds. In some Cortex-M0 microcontrollers a reference value is not available. Also some microcontrollers do not have an external reference clock source for the SysTick timer, in such case the NOREF bit is set to one to reflect this." |
327 | Example code for putting LPC1114 in low power mode. The bit definition for LPC_SYSCON->PDSLEEPCFG is wrong in the code. You can program it as: LPC_SYSCON->PDSLEEPCFG = 0x000018BF; // WD osc on, BOD off |
Comments